<commit_before>//===- DeadStoreElimination.cpp - Dead Store Elimination ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Owen Anderson and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a trivial dead store elimination that only considers
// basic-block local redundant stores.
//
// FIXME: This should eventually be extended to be a post-dominator tree
// traversal.  Doing so would be pretty trivial.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "fdse"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

STATISTIC(NumFastStores, "Number of stores deleted");
STATISTIC(NumFastOther , "Number of other instrs removed");

namespace {
  struct VISIBILITY_HIDDEN FDSE : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    FDSE() : FunctionPass((intptr_t)&ID) {}

    virtual bool runOnFunction(Function &F) {
      bool Changed = false;
      for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
        Changed |= runOnBasicBlock(*I);
      return Changed;
    }

    bool runOnBasicBlock(BasicBlock &BB);
    bool handleFreeWithNonTrivialDependency(FreeInst* F, Instruction* dependency,
                                            SetVector<Instruction*>& possiblyDead);
    bool handleEndBlock(BasicBlock& BB, SetVector<Instruction*>& possiblyDead);
    bool RemoveUndeadPointers(Value* pointer, unsigned pointerSize,
                              BasicBlock::iterator& BBI,
                              SmallPtrSet<AllocaInst*, 4>& deadPointers,
                              SetVector<Instruction*>& possiblyDead);
    void DeleteDeadInstructionChains(Instruction *I,
                                     SetVector<Instruction*> &DeadInsts);
    void TranslatePointerBitCasts(Value*& v) {
      assert(isa<PointerType>(v->getType()) && "Translating a non-pointer type?");

      // See through pointer-to-pointer bitcasts
      while (BitCastInst* C = dyn_cast<BitCastInst>(v))
        if (isa<PointerType>(C->getSrcTy()))
          v = C->getOperand(0);
    }

    // getAnalysisUsage - We require post dominance frontiers (aka Control
    // Dependence Graph)
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequired<TargetData>();
      AU.addRequired<AliasAnalysis>();
      AU.addRequired<MemoryDependenceAnalysis>();
      AU.addPreserved<AliasAnalysis>();
      AU.addPreserved<MemoryDependenceAnalysis>();
    }
  };
  char FDSE::ID = 0;
  RegisterPass<FDSE> X("fdse", "Fast Dead Store Elimination");
}

FunctionPass *llvm::createFastDeadStoreEliminationPass() { return new FDSE(); }

bool FDSE::runOnBasicBlock(BasicBlock &BB) {
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  // Record the last-seen store to this pointer
  DenseMap<Value*, StoreInst*> lastStore;
  // Record instructions possibly made dead by deleting a store
  SetVector<Instruction*> possiblyDead;

  bool MadeChange = false;

  // Do a top-down walk on the BB
  for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ++BBI) {
    // If we find a store or a free...
    if (isa<StoreInst>(BBI) || isa<FreeInst>(BBI)) {
      Value* pointer = 0;
      if (StoreInst* S = dyn_cast<StoreInst>(BBI))
        pointer = S->getPointerOperand();
      else if (FreeInst* F = dyn_cast<FreeInst>(BBI))
        pointer = F->getPointerOperand();

      assert(pointer && "Not a free or a store?");

      StoreInst*& last = lastStore[pointer];
      bool deletedStore = false;

      // ... to a pointer that has been stored to before...
      if (last) {

        // ... and no other memory dependencies are between them....
        if (MD.getDependency(BBI) == last) {

          // Remove it!
          MD.removeInstruction(last);

          // DCE instructions only used to calculate that store
          if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
            possiblyDead.insert(D);
          if (Instruction* D = dyn_cast<Instruction>(last->getOperand(1)))
            possiblyDead.insert(D);

          last->eraseFromParent();
          NumFastStores++;
          deletedStore = true;
          MadeChange = true;
        }
      }

      // Handle frees whose dependencies are non-trivial
      if (FreeInst* F = dyn_cast<FreeInst>(BBI))
        if (!deletedStore)
          MadeChange |= handleFreeWithNonTrivialDependency(F, MD.getDependency(F),
                                                           possiblyDead);

      // Update our most-recent-store map
      if (StoreInst* S = dyn_cast<StoreInst>(BBI))
        last = S;
      else
        last = 0;
    }
  }

  // If this block ends in a return, unwind, unreachable, and eventually
  // tailcall, then all allocas are dead at its end.
  if (BB.getTerminator()->getNumSuccessors() == 0)
    MadeChange |= handleEndBlock(BB, possiblyDead);

  // Do a trivial DCE
  while (!possiblyDead.empty()) {
    Instruction *I = possiblyDead.back();
    possiblyDead.pop_back();
    DeleteDeadInstructionChains(I, possiblyDead);
  }

  return MadeChange;
}

/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose
/// dependency is a store to a field of that structure
bool FDSE::handleFreeWithNonTrivialDependency(FreeInst* F, Instruction* dep,
                                              SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  if (dep == MemoryDependenceAnalysis::None ||
      dep == MemoryDependenceAnalysis::NonLocal)
    return false;

  StoreInst* dependency = dyn_cast<StoreInst>(dep);
  if (!dependency)
    return false;

  Value* depPointer = dependency->getPointerOperand();
  unsigned depPointerSize = TD.getTypeSize(dependency->getOperand(0)->getType());

  // Check for aliasing
  AliasAnalysis::AliasResult A = AA.alias(F->getPointerOperand(), ~0UL,
                                          depPointer, depPointerSize);

  if (A == AliasAnalysis::MustAlias) {
    // Remove it!
    MD.removeInstruction(dependency);

    // DCE instructions only used to calculate that store
    if (Instruction* D = dyn_cast<Instruction>(dependency->getOperand(0)))
      possiblyDead.insert(D);
    if (Instruction* D = dyn_cast<Instruction>(dependency->getOperand(1)))
      possiblyDead.insert(D);

    dependency->eraseFromParent();
    NumFastStores++;
    return true;
  }

  return false;
}

/// handleEndBlock - Remove dead stores to stack-allocated locations in the function
/// end block
bool FDSE::handleEndBlock(BasicBlock& BB, SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  bool MadeChange = false;

  // Pointers alloca'd in this function are dead in the end block
  SmallPtrSet<AllocaInst*, 4> deadPointers;

  // Find all of the alloca'd pointers in the entry block
  BasicBlock *Entry = BB.getParent()->begin();
  for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I)
    if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
      deadPointers.insert(AI);

  // Scan the basic block backwards
  for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){
    --BBI;

    if (deadPointers.empty())
      break;

    Value* killPointer = 0;
    unsigned killPointerSize = 0;

    // If we find a store whose pointer is dead...
    if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
      Value* pointerOperand = S->getPointerOperand();
      // See through pointer-to-pointer bitcasts
      TranslatePointerBitCasts(pointerOperand);

      if (deadPointers.count(pointerOperand)){
        // Remove it!
        MD.removeInstruction(S);

        // DCE instructions only used to calculate that store
        if (Instruction* D = dyn_cast<Instruction>(S->getOperand(0)))
          possiblyDead.insert(D);
        if (Instruction* D = dyn_cast<Instruction>(S->getOperand(1)))
          possiblyDead.insert(D);

        BBI++;
        S->eraseFromParent();
        NumFastStores++;
        MadeChange = true;
      }

    // If we encounter a use of the pointer, it is no longer considered dead
    } else if (LoadInst* L = dyn_cast<LoadInst>(BBI)) {
      killPointer = L->getPointerOperand();
      killPointerSize = TD.getTypeSize(L->getType());
    } else if (VAArgInst* V = dyn_cast<VAArgInst>(BBI)) {
      killPointer = V->getOperand(0);
      killPointerSize = TD.getTypeSize(V->getType());
    } else if (FreeInst* F = dyn_cast<FreeInst>(BBI)) {
      killPointer = F->getPointerOperand();
      killPointerSize = ~0UL;
    } else if (AllocaInst* A = dyn_cast<AllocaInst>(BBI)) {
      deadPointers.erase(A);
      continue;
    } else if (CallSite::get(BBI).getInstruction() != 0) {
      // Remove any pointers made undead by the call from the dead set
      std::vector<Instruction*> dead;
      for (SmallPtrSet<AllocaInst*, 4>::iterator I = deadPointers.begin(),
           E = deadPointers.end(); I != E; ++I) {
        // Get size information for the alloca
        unsigned pointerSize = ~0UL;
        if (ConstantInt* C = dyn_cast<ConstantInt>((*I)->getArraySize()))
          pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType());

        // See if the call site touches it
        AliasAnalysis::ModRefResult A = AA.getModRefInfo(CallSite::get(BBI),
                                                         *I, pointerSize);
        if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref)
          dead.push_back(*I);
      }

      for (std::vector<Instruction*>::iterator I = dead.begin(), E = dead.end();
           I != E; ++I)
        deadPointers.erase(*I);

      continue;
    }

    if (!killPointer)
      continue;

    // Deal with undead pointers
    MadeChange |= RemoveUndeadPointers(killPointer, killPointerSize, BBI,
                                       deadPointers, possiblyDead);
  }

  return MadeChange;
}

bool FDSE::RemoveUndeadPointers(Value* killPointer, unsigned killPointerSize,
                                BasicBlock::iterator& BBI,
                                SmallPtrSet<AllocaInst*, 4>& deadPointers,
                                SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  bool MadeChange = false;

  std::vector<Instruction*> undead;

  for (SmallPtrSet<AllocaInst*, 4>::iterator I = deadPointers.begin(),
      E = deadPointers.end(); I != E; ++I) {
    // Get size information for the alloca
    unsigned pointerSize = ~0UL;
    if (ConstantInt* C = dyn_cast<ConstantInt>((*I)->getArraySize()))
      pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType());

    // See if this pointer could alias it
    AliasAnalysis::AliasResult A = AA.alias(*I, pointerSize, killPointer, killPointerSize);

    // If it must-alias and a store, we can delete it
    if (isa<StoreInst>(BBI) && A == AliasAnalysis::MustAlias) {
      StoreInst* S = cast<StoreInst>(BBI);

      // Remove it!
      MD.removeInstruction(S);

      // DCE instructions only used to calculate that store
      if (Instruction* D = dyn_cast<Instruction>(S->getOperand(0)))
        possiblyDead.insert(D);
      if (Instruction* D = dyn_cast<Instruction>(S->getOperand(1)))
        possiblyDead.insert(D);

      BBI++;
      S->eraseFromParent();
      NumFastStores++;
      MadeChange = true;

      continue;

      // Otherwise, it is undead
      } else if (A != AliasAnalysis::NoAlias)
        undead.push_back(*I);
  }

  for (std::vector<Instruction*>::iterator I = undead.begin(), E = undead.end();
       I != E; ++I)
    deadPointers.erase(*I);

  return MadeChange;
}

void FDSE::DeleteDeadInstructionChains(Instruction *I,
                                      SetVector<Instruction*> &DeadInsts) {
  // Instruction must be dead.
  if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;

  // Let the memory dependence know
  getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);

  // See if this made any operands dead.  We do it this way in case the
  // instruction uses the same operand twice.  We don't want to delete a
  // value then reference it.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    if (I->getOperand(i)->hasOneUse())
      if (Instruction* Op = dyn_cast<Instruction>(I->getOperand(i)))
        DeadInsts.insert(Op);      // Attempt to nuke it later.

    I->setOperand(i, 0);         // Drop from the operand list.
  }

  I->eraseFromParent();
  ++NumFastOther;
}
<commit_msg>Handle GEPs with all-zero indices in the same way we handle pointer-pointer bitcasts. Also, fix a potentia infinite loop.<commit_after>//===- DeadStoreElimination.cpp - Dead Store Elimination ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Owen Anderson and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a trivial dead store elimination that only considers
// basic-block local redundant stores.
//
// FIXME: This should eventually be extended to be a post-dominator tree
// traversal.  Doing so would be pretty trivial.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "fdse"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

STATISTIC(NumFastStores, "Number of stores deleted");
STATISTIC(NumFastOther , "Number of other instrs removed");

namespace {
  struct VISIBILITY_HIDDEN FDSE : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    FDSE() : FunctionPass((intptr_t)&ID) {}

    virtual bool runOnFunction(Function &F) {
      bool Changed = false;
      for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
        Changed |= runOnBasicBlock(*I);
      return Changed;
    }

    bool runOnBasicBlock(BasicBlock &BB);
    bool handleFreeWithNonTrivialDependency(FreeInst* F, Instruction* dependency,
                                            SetVector<Instruction*>& possiblyDead);
    bool handleEndBlock(BasicBlock& BB, SetVector<Instruction*>& possiblyDead);
    bool RemoveUndeadPointers(Value* pointer, unsigned pointerSize,
                              BasicBlock::iterator& BBI,
                              SmallPtrSet<AllocaInst*, 4>& deadPointers,
                              SetVector<Instruction*>& possiblyDead);
    void DeleteDeadInstructionChains(Instruction *I,
                                     SetVector<Instruction*> &DeadInsts);
    void TranslatePointerBitCasts(Value*& v) {
      assert(isa<PointerType>(v->getType()) && "Translating a non-pointer type?");

      // See through pointer-to-pointer bitcasts
      while (isa<BitCastInst>(v) || isa<GetElementPtrInst>(v))
        if (BitCastInst* C = dyn_cast<BitCastInst>(v)) {
          if (isa<PointerType>(C->getSrcTy()))
            v = C->getOperand(0);
          else
            break;
        } else if (GetElementPtrInst* G = dyn_cast<GetElementPtrInst>(v)) {
          if (G->hasAllZeroIndices())
            v = G->getOperand(0);
          else
            break;
        }
    }

    // getAnalysisUsage - We require post dominance frontiers (aka Control
    // Dependence Graph)
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequired<TargetData>();
      AU.addRequired<AliasAnalysis>();
      AU.addRequired<MemoryDependenceAnalysis>();
      AU.addPreserved<AliasAnalysis>();
      AU.addPreserved<MemoryDependenceAnalysis>();
    }
  };
  char FDSE::ID = 0;
  RegisterPass<FDSE> X("fdse", "Fast Dead Store Elimination");
}

FunctionPass *llvm::createFastDeadStoreEliminationPass() { return new FDSE(); }

bool FDSE::runOnBasicBlock(BasicBlock &BB) {
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  // Record the last-seen store to this pointer
  DenseMap<Value*, StoreInst*> lastStore;
  // Record instructions possibly made dead by deleting a store
  SetVector<Instruction*> possiblyDead;

  bool MadeChange = false;

  // Do a top-down walk on the BB
  for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ++BBI) {
    // If we find a store or a free...
    if (isa<StoreInst>(BBI) || isa<FreeInst>(BBI)) {
      Value* pointer = 0;
      if (StoreInst* S = dyn_cast<StoreInst>(BBI))
        pointer = S->getPointerOperand();
      else if (FreeInst* F = dyn_cast<FreeInst>(BBI))
        pointer = F->getPointerOperand();

      assert(pointer && "Not a free or a store?");

      StoreInst*& last = lastStore[pointer];
      bool deletedStore = false;

      // ... to a pointer that has been stored to before...
      if (last) {

        // ... and no other memory dependencies are between them....
        if (MD.getDependency(BBI) == last) {

          // Remove it!
          MD.removeInstruction(last);

          // DCE instructions only used to calculate that store
          if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
            possiblyDead.insert(D);
          if (Instruction* D = dyn_cast<Instruction>(last->getOperand(1)))
            possiblyDead.insert(D);

          last->eraseFromParent();
          NumFastStores++;
          deletedStore = true;
          MadeChange = true;
        }
      }

      // Handle frees whose dependencies are non-trivial
      if (FreeInst* F = dyn_cast<FreeInst>(BBI))
        if (!deletedStore)
          MadeChange |= handleFreeWithNonTrivialDependency(F, MD.getDependency(F),
                                                           possiblyDead);

      // Update our most-recent-store map
      if (StoreInst* S = dyn_cast<StoreInst>(BBI))
        last = S;
      else
        last = 0;
    }
  }

  // If this block ends in a return, unwind, unreachable, and eventually
  // tailcall, then all allocas are dead at its end.
  if (BB.getTerminator()->getNumSuccessors() == 0)
    MadeChange |= handleEndBlock(BB, possiblyDead);

  // Do a trivial DCE
  while (!possiblyDead.empty()) {
    Instruction *I = possiblyDead.back();
    possiblyDead.pop_back();
    DeleteDeadInstructionChains(I, possiblyDead);
  }

  return MadeChange;
}

/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose
/// dependency is a store to a field of that structure
bool FDSE::handleFreeWithNonTrivialDependency(FreeInst* F, Instruction* dep,
                                              SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  if (dep == MemoryDependenceAnalysis::None ||
      dep == MemoryDependenceAnalysis::NonLocal)
    return false;

  StoreInst* dependency = dyn_cast<StoreInst>(dep);
  if (!dependency)
    return false;

  Value* depPointer = dependency->getPointerOperand();
  unsigned depPointerSize = TD.getTypeSize(dependency->getOperand(0)->getType());

  // Check for aliasing
  AliasAnalysis::AliasResult A = AA.alias(F->getPointerOperand(), ~0UL,
                                          depPointer, depPointerSize);

  if (A == AliasAnalysis::MustAlias) {
    // Remove it!
    MD.removeInstruction(dependency);

    // DCE instructions only used to calculate that store
    if (Instruction* D = dyn_cast<Instruction>(dependency->getOperand(0)))
      possiblyDead.insert(D);
    if (Instruction* D = dyn_cast<Instruction>(dependency->getOperand(1)))
      possiblyDead.insert(D);

    dependency->eraseFromParent();
    NumFastStores++;
    return true;
  }

  return false;
}

/// handleEndBlock - Remove dead stores to stack-allocated locations in the function
/// end block
bool FDSE::handleEndBlock(BasicBlock& BB, SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  bool MadeChange = false;

  // Pointers alloca'd in this function are dead in the end block
  SmallPtrSet<AllocaInst*, 4> deadPointers;

  // Find all of the alloca'd pointers in the entry block
  BasicBlock *Entry = BB.getParent()->begin();
  for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I)
    if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
      deadPointers.insert(AI);

  // Scan the basic block backwards
  for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){
    --BBI;

    if (deadPointers.empty())
      break;

    Value* killPointer = 0;
    unsigned killPointerSize = 0;

    // If we find a store whose pointer is dead...
    if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
      Value* pointerOperand = S->getPointerOperand();
      // See through pointer-to-pointer bitcasts
      TranslatePointerBitCasts(pointerOperand);

      if (deadPointers.count(pointerOperand)){
        // Remove it!
        MD.removeInstruction(S);

        // DCE instructions only used to calculate that store
        if (Instruction* D = dyn_cast<Instruction>(S->getOperand(0)))
          possiblyDead.insert(D);
        if (Instruction* D = dyn_cast<Instruction>(S->getOperand(1)))
          possiblyDead.insert(D);

        BBI++;
        S->eraseFromParent();
        NumFastStores++;
        MadeChange = true;
      }

    // If we encounter a use of the pointer, it is no longer considered dead
    } else if (LoadInst* L = dyn_cast<LoadInst>(BBI)) {
      killPointer = L->getPointerOperand();
      killPointerSize = TD.getTypeSize(L->getType());
    } else if (VAArgInst* V = dyn_cast<VAArgInst>(BBI)) {
      killPointer = V->getOperand(0);
      killPointerSize = TD.getTypeSize(V->getType());
    } else if (FreeInst* F = dyn_cast<FreeInst>(BBI)) {
      killPointer = F->getPointerOperand();
      killPointerSize = ~0UL;
    } else if (AllocaInst* A = dyn_cast<AllocaInst>(BBI)) {
      deadPointers.erase(A);
      continue;
    } else if (CallSite::get(BBI).getInstruction() != 0) {
      // Remove any pointers made undead by the call from the dead set
      std::vector<Instruction*> dead;
      for (SmallPtrSet<AllocaInst*, 4>::iterator I = deadPointers.begin(),
           E = deadPointers.end(); I != E; ++I) {
        // Get size information for the alloca
        unsigned pointerSize = ~0UL;
        if (ConstantInt* C = dyn_cast<ConstantInt>((*I)->getArraySize()))
          pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType());

        // See if the call site touches it
        AliasAnalysis::ModRefResult A = AA.getModRefInfo(CallSite::get(BBI),
                                                         *I, pointerSize);
        if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref)
          dead.push_back(*I);
      }

      for (std::vector<Instruction*>::iterator I = dead.begin(), E = dead.end();
           I != E; ++I)
        deadPointers.erase(*I);

      continue;
    }

    if (!killPointer)
      continue;

    // Deal with undead pointers
    MadeChange |= RemoveUndeadPointers(killPointer, killPointerSize, BBI,
                                       deadPointers, possiblyDead);
  }

  return MadeChange;
}

bool FDSE::RemoveUndeadPointers(Value* killPointer, unsigned killPointerSize,
                                BasicBlock::iterator& BBI,
                                SmallPtrSet<AllocaInst*, 4>& deadPointers,
                                SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();

  bool MadeChange = false;

  std::vector<Instruction*> undead;

  for (SmallPtrSet<AllocaInst*, 4>::iterator I = deadPointers.begin(),
      E = deadPointers.end(); I != E; ++I) {
    // Get size information for the alloca
    unsigned pointerSize = ~0UL;
    if (ConstantInt* C = dyn_cast<ConstantInt>((*I)->getArraySize()))
      pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType());

    // See if this pointer could alias it
    AliasAnalysis::AliasResult A = AA.alias(*I, pointerSize, killPointer, killPointerSize);

    // If it must-alias and a store, we can delete it
    if (isa<StoreInst>(BBI) && A == AliasAnalysis::MustAlias) {
      StoreInst* S = cast<StoreInst>(BBI);

      // Remove it!
      MD.removeInstruction(S);

      // DCE instructions only used to calculate that store
      if (Instruction* D = dyn_cast<Instruction>(S->getOperand(0)))
        possiblyDead.insert(D);
      if (Instruction* D = dyn_cast<Instruction>(S->getOperand(1)))
        possiblyDead.insert(D);

      BBI++;
      S->eraseFromParent();
      NumFastStores++;
      MadeChange = true;

      continue;

      // Otherwise, it is undead
      } else if (A != AliasAnalysis::NoAlias)
        undead.push_back(*I);
  }

  for (std::vector<Instruction*>::iterator I = undead.begin(), E = undead.end();
       I != E; ++I)
    deadPointers.erase(*I);

  return MadeChange;
}

void FDSE::DeleteDeadInstructionChains(Instruction *I,
                                      SetVector<Instruction*> &DeadInsts) {
  // Instruction must be dead.
  if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;

  // Let the memory dependence know
  getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);

  // See if this made any operands dead.  We do it this way in case the
  // instruction uses the same operand twice.  We don't want to delete a
  // value then reference it.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    if (I->getOperand(i)->hasOneUse())
      if (Instruction* Op = dyn_cast<Instruction>(I->getOperand(i)))
        DeadInsts.insert(Op);      // Attempt to nuke it later.

    I->setOperand(i, 0);         // Drop from the operand list.
  }

  I->eraseFromParent();
  ++NumFastOther;
}
<|endoftext|>


<commit_before>//
//  nthRoot.cpp
//  Calculator
//
//  Created by Gavin Scheele on 3/27/14.
//  Copyright (c) 2014 Gavin Scheele. All rights reserved.
//

#include "nthRoot.h"
#include "Integer.h"
#include <array>
using namespace std;
nthRoot::nthRoot(int root, int operand, int coefficient) {
    this->type = "nthRoot";
    this->operand = operand;
    this->root = root;
    this->coefficient = coefficient;
    this->simplify();

    if ((root % 2) == 0 && operand < 0) {
        throw runtime_error("unreal answer");
    }
}

nthRoot::nthRoot(int root, Expression* eoperand, int coefficient) {
    this->type = "nthRoot";
    this->eoperand = eoperand;
    this->root = root;
    this->coefficient = coefficient;

    if ((root % 2) == 0 && eoperand->type == "integer") {
        Integer *a = (Integer *)eoperand;
        if (a->getValue() < 0) {
            throw runtime_error("unreal answer");
        }
    }

    if ((root % 2) == 0 && eoperand->type == "Rational"){
        Rational *b = (Rational*)eoperand;
        if ((b->getNumerator() < 0 || b->getDenominator() < 0)
             && !(b->getNumerator() < 0 && b->getDenominator() < 0)) {
             throw runtime_error("unreal answer");
        }
    }
}

nthRoot::~nthRoot() {

}

 int* nthRoot::primeFactorization(int n, int div, int k) {
    if (n % div == 0) {
        factors[k] = div;
        if (div == n) {
            factors[k+1] = 0; //the zero works as a stopping point later on
            return factors;
        }
        else {
            primeFactorization((n / div), div, (k + 1));
        }
    }
    else if (div <= n) {
        primeFactorization(n, (div + 1), k);
    }
    return factors;
}

int nthRoot::localExponentiate(int base, int locExponent) {
    if (locExponent >= 1)
        return base * (localExponentiate(base, locExponent - 1));
    else return 1;
}

/*
int nthRoot::localExponentiate(int under, int locExponent) {
    for (int i = 1; i < locExponent; i++) {
        under *= under;
    }
//    cout << under << "\n";
    return under;
}
*/
/*int* nthRoot::primeFactorization(int n, int num, int number) {    //non-recursive version
    int k = 0;
    int* factors;
    while (n%2 == 0) {
        factors[k] = 2;
        k++;
        n = n/2;
    }
    for (int i = 3; i <= sqrt(n); i = i + 2) {
//        if (n%i == 0) {
            while (n%i == 0) {
                factors[k] = i;
                k++;
                n = n/i;
            }
//        }
    }
    if (n > 2) {
        factors[k] = n;
    }
    n = 3;
    return factors;
    // added bonus: factors should be sorted already
} */

Expression* nthRoot::simplify(){
    //if coefficient == 0 then return 0?
    //if operand < 0 throw an error
    if ((root % 2) == 0 && operand < 0) {
        throw runtime_error("unreal answer");
    }
//    int *factorsCopy = this->primeFactorization(operand, 2, 0);
      this->primeFactorization(operand, 2, 0);
//    copy(this->primeFactorization(operand, 2, 0)+50, factors);
    int i = 0;
    int factorsSize = sizeof(factors)/sizeof(factors[0]);

    while (i <= factorsSize && factors[i] != 0) {   //all this takes unnecessary factors out of the operand
        int j = i;               //and puts them into the coefficient
        int count = 1;
        while (j <= factorsSize && factors[j + 1] == factors[j] && factors[j] != 0) {
            count++;
            j++;
        }
        if (count >= root) {

            coefficient = coefficient * localExponentiate(factors[i], (count/root));
            operand = (operand / localExponentiate(factors[i], (count - (count % root))));
        }
        i = j + 1;
    }
    if (operand == 1) {
        Integer* newInt = new Integer(coefficient);
        return newInt;
    }
    else {
        Expression* newRoot = new nthRoot(root, operand, coefficient);
        return newRoot;
    }

}

Expression* nthRoot::add(Expression* a) {
    nthRoot *b = (nthRoot *)a;
    int asCoefficient = b->getCoefficient();
    int asOperand = b->getOperand();
    int asRoot = b->getRoot();
    if (root == asRoot && operand == asOperand) {
        int newCoefficient = asCoefficient + coefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    else {
        return this;
    }
}

Expression* nthRoot::subtract(Expression* a) {
    nthRoot *b = (nthRoot *)a;
    int asCoefficient = b->getCoefficient();
    int asOperand = b->getOperand();
    int asRoot = b->getRoot();
    if (root == asRoot && operand == asOperand) {
        int newCoefficient = coefficient - asCoefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    else {
        return this;
    }
}

Expression* nthRoot::multiply(Expression* a) {
    if (a->type == "integer") {
        Integer *b = (Integer*)a;
        int asValue = b->getValue();
        int newCoefficient = asValue * coefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    if (a->type == "nthRoot") {
        nthRoot *b = (nthRoot *)a;
        int asCoefficient = b->getCoefficient();
        int asOperand = b->getOperand();
        int asRoot = b->getRoot();
        if (root == asRoot) {
            int newCoefficient = asCoefficient * coefficient;
            int newOperand = operand * asOperand;       //asOperand doesnt exist?
            nthRoot* newNthRoot = new nthRoot(root, newOperand, newCoefficient);
            nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
            return simplifiedVersion;
        }
    }
    else {
        return this;
    }
    return this;
}

Expression* nthRoot::divide(Expression* a) {
    nthRoot *b = (nthRoot *)a;
    int asRoot = b->getRoot();
    int asOperand = b->getOperand();
    int asCoefficient = b->getCoefficient();
    if (root == asRoot && fmod( ((double)coefficient / (double)asCoefficient), 1) == 0 && fmod(((double)operand / (double)asOperand), 1) == 0) {
        int newCoefficient = coefficient / asCoefficient;
        int newOperand = operand / asOperand;
        nthRoot* newNthRoot = new nthRoot(root, newOperand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
   else if (fmod( ((double)coefficient / (double)asCoefficient),1) == 0) {
        int newCoefficient = coefficient / asCoefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    else {
        return this;
    }
}

int nthRoot::getRoot() {
    return root;
}

int nthRoot::getOperand() {
    return operand;
}

int nthRoot::getCoefficient() {
    return coefficient;
}

void nthRoot::setCoefficient(int n) {
    this->coefficient = n;
}

void nthRoot::setOperand(int n) {
    this->operand = n;
}

void nthRoot::setRoot(int n) {
    this->root = n;
}
ostream& nthRoot::print(std::ostream& output) const {
    if (this->operand == 1) {
        output << this->coefficient;
    }else{
        output << this->coefficient  << "*" << this->root << "rt:" << this->operand;
    }
    return output;
}

string nthRoot::toString() {
    stringstream s;
    if (this->operand == 1) {
        s << this->coefficient;
    }else{
        s << this->coefficient  << "*" << this->root << "rt:" << this->operand;
    }
    return s.str();
}

bool nthRoot::canAdd(Expression* b){     //use "this" as comparison. Solver will call someExpression.canAdd(&someOtherExpression)

    if (this->type == b->type && this->type != "logarithm") {
        if (this->type == "nthRoot") {
        }
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool nthRoot::canSubtract(Expression* b){
    if (this->type == b->type) {
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool nthRoot::canMultiply(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer" && b->type == "rational") return true;
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;

}
bool nthRoot::canDivide(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer"){
        if( b->type == "rational") return true;
    }
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
<commit_msg>gav you rock<commit_after>//
//  nthRoot.cpp
//  Calculator
//
//  Created by Gavin Scheele on 3/27/14.
//  Copyright (c) 2014 Gavin Scheele. All rights reserved.
//

#include "nthRoot.h"
#include "Integer.h"
#include <array>
using namespace std;
nthRoot::nthRoot(int root, int operand, int coefficient) {
    this->type = "nthRoot";
    this->operand = operand;
    this->root = root;
    this->coefficient = coefficient;
    this->simplify();

    if ((root % 2) == 0 && operand < 0) {
        throw runtime_error("unreal answer");
    }
}

nthRoot::nthRoot(int root, Expression* eoperand, int coefficient) {
    this->type = "nthRoot";
    this->eoperand = eoperand;
    this->root = root;
    this->coefficient = coefficient;

    if ((root % 2) == 0 && eoperand->type == "integer") {
        Integer *a = (Integer *)eoperand;
        if (a->getValue() < 0) {
            throw runtime_error("unreal answer");
        }
    }

    if ((root % 2) == 0 && eoperand->type == "Rational"){
        Rational *b = (Rational*)eoperand;
        if ((b->getNumerator() < 0 || b->getDenominator() < 0)
             && !(b->getNumerator() < 0 && b->getDenominator() < 0)) {
             throw runtime_error("unreal answer");
        }
    }
}

nthRoot::~nthRoot() {

}

 int* nthRoot::primeFactorization(int n, int div, int k) {
    if (n % div == 0) {
        factors[k] = div;
        if (div == n) {
            factors[k+1] = 0; //the zero works as a stopping point later on
            return factors;
        }
        else {
            primeFactorization((n / div), div, (k + 1));
        }
    }
    else if (div <= n) {
        primeFactorization(n, (div + 1), k);
    }
    return factors;
}

int nthRoot::localExponentiate(int base, int locExponent) {
    if (locExponent >= 1)
        return base * (localExponentiate(base, locExponent - 1));
    else return 1;
}

/*
int nthRoot::localExponentiate(int under, int locExponent) {
    for (int i = 1; i < locExponent; i++) {
        under *= under;
    }
//    cout << under << "\n";
    return under;
}
*/
/*int* nthRoot::primeFactorization(int n, int num, int number) {    //non-recursive version
    int k = 0;
    int* factors;
    while (n%2 == 0) {
        factors[k] = 2;
        k++;
        n = n/2;
    }
    for (int i = 3; i <= sqrt(n); i = i + 2) {
//        if (n%i == 0) {
            while (n%i == 0) {
                factors[k] = i;
                k++;
                n = n/i;
            }
//        }
    }
    if (n > 2) {
        factors[k] = n;
    }
    n = 3;
    return factors;
    // added bonus: factors should be sorted already
} */

Expression* nthRoot::simplify(){
    //if coefficient == 0 then return 0?
    //if operand < 0 throw an error
    if ((root % 2) == 0 && operand < 0) {
        throw runtime_error("unreal answer");
    }
//    int *factorsCopy = this->primeFactorization(operand, 2, 0);
      this->primeFactorization(operand, 2, 0);
//    copy(this->primeFactorization(operand, 2, 0)+50, factors);
    int i = 0;
    int factorsSize = sizeof(factors)/sizeof(factors[0]);

    while (i <= factorsSize && factors[i] != 0) {   //all this takes unnecessary factors out of the operand
        int j = i;               //and puts them into the coefficient
        int count = 1;
        while (j <= factorsSize && factors[j + 1] == factors[j] && factors[j] != 0) {
            count++;
            j++;
        }
        if (count >= root) {

            coefficient = coefficient * localExponentiate(factors[i], (count/root));
            operand = (operand / localExponentiate(factors[i], (count - (count % root))));
        }
        i = j + 1;
    }
    if (operand == 1) {
        Integer* newInt = new Integer(coefficient);
        return newInt;
    }
    else {
        /*Expression* newRoot = new nthRoot(root, operand, coefficient);
        return newRoot; */
        return this;
    }

}

Expression* nthRoot::add(Expression* a) {
    nthRoot *b = (nthRoot *)a;
    int asCoefficient = b->getCoefficient();
    int asOperand = b->getOperand();
    int asRoot = b->getRoot();
    if (root == asRoot && operand == asOperand) {
        int newCoefficient = asCoefficient + coefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    else {
        return this;
    }
}

Expression* nthRoot::subtract(Expression* a) {
    nthRoot *b = (nthRoot *)a;
    int asCoefficient = b->getCoefficient();
    int asOperand = b->getOperand();
    int asRoot = b->getRoot();
    if (root == asRoot && operand == asOperand) {
        int newCoefficient = coefficient - asCoefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    else {
        return this;
    }
}

Expression* nthRoot::multiply(Expression* a) {
    if (a->type == "integer") {
        Integer *b = (Integer*)a;
        int asValue = b->getValue();
        int newCoefficient = asValue * coefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    if (a->type == "nthRoot") {
        nthRoot *b = (nthRoot *)a;
        int asCoefficient = b->getCoefficient();
        int asOperand = b->getOperand();
        int asRoot = b->getRoot();
        if (root == asRoot) {
            int newCoefficient = asCoefficient * coefficient;
            int newOperand = operand * asOperand;       //asOperand doesnt exist?
            nthRoot* newNthRoot = new nthRoot(root, newOperand, newCoefficient);
            nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
            return simplifiedVersion;
        }
    }
    else {
        return this;
    }
    return this;
}

Expression* nthRoot::divide(Expression* a) {
    nthRoot *b = (nthRoot *)a;
    int asRoot = b->getRoot();
    int asOperand = b->getOperand();
    int asCoefficient = b->getCoefficient();
    if (root == asRoot && fmod( ((double)coefficient / (double)asCoefficient), 1) == 0 && fmod(((double)operand / (double)asOperand), 1) == 0) {
        int newCoefficient = coefficient / asCoefficient;
        int newOperand = operand / asOperand;
        nthRoot* newNthRoot = new nthRoot(root, newOperand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
   else if (fmod( ((double)coefficient / (double)asCoefficient),1) == 0) {
        int newCoefficient = coefficient / asCoefficient;
        nthRoot* newNthRoot = new nthRoot(root, operand, newCoefficient);
        nthRoot* simplifiedVersion = (nthRoot *)newNthRoot->simplify();
        return simplifiedVersion;
    }
    else {
        return this;
    }
}

int nthRoot::getRoot() {
    return root;
}

int nthRoot::getOperand() {
    return operand;
}

int nthRoot::getCoefficient() {
    return coefficient;
}

void nthRoot::setCoefficient(int n) {
    this->coefficient = n;
}

void nthRoot::setOperand(int n) {
    this->operand = n;
}

void nthRoot::setRoot(int n) {
    this->root = n;
}
ostream& nthRoot::print(std::ostream& output) const {
    if (this->operand == 1) {
        output << this->coefficient;
    }else{
        output << this->coefficient  << "*" << this->root << "rt:" << this->operand;
    }
    return output;
}

string nthRoot::toString() {
    stringstream s;
    if (this->operand == 1) {
        s << this->coefficient;
    }else{
        s << this->coefficient  << "*" << this->root << "rt:" << this->operand;
    }
    return s.str();
}

bool nthRoot::canAdd(Expression* b){     //use "this" as comparison. Solver will call someExpression.canAdd(&someOtherExpression)

    if (this->type == b->type && this->type != "logarithm") {
        if (this->type == "nthRoot") {
        }
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool nthRoot::canSubtract(Expression* b){
    if (this->type == b->type) {
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool nthRoot::canMultiply(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer" && b->type == "rational") return true;
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;

}
bool nthRoot::canDivide(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer"){
        if( b->type == "rational") return true;
    }
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
<|endoftext|>


<commit_before>#include "interrupt.h"

namespace Interrupt {
	MFP mf_vectors[16 + NUM_IRQs];
};

void entry();

void member_function_interrupt_gate() {
	uint32_t interrupt_num;
	asm ("mrs %0, ipsr" : "=r" (interrupt_num));

	Interrupt::mf_vectors[interrupt_num].func_p(Interrupt::mf_vectors[interrupt_num].instance_p);
}

extern "C" void unused_interrupt() {
	member_function_interrupt_gate();
	//while(1);
}

template<> void interrupt<Interrupt::NMI>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::HardFault>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::MemManage>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::BusFault>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::UsageFault>()      __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SVCall>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::PendSV>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SysTick>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::WWDG>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::PVD>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TAMPER>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::RTC>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::FLASH>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::RCC>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI0>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI1>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI2>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI3>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI4>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel1>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel2>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel3>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel4>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel5>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel6>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel7>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::ADC1_2>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USB_HP_CAN_TX>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USB_LP_CAN_RX0>()  __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::CAN_RX1>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::CAN_SCE>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI9_5>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_BRK>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_UP>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_TRG_COM>()    __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_CC>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM2>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM3>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM4>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C1_EV>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C1_ER>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C2_EV>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C2_ER>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SPI1>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SPI2>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USART1>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USART2>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USART3>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI15_10>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::RTCAlarm>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USBWakeup>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_BRK>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_UP>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_TRG_COM>()    __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_CC>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::ADC3>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::FSMC>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SDIO>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM5>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SPI3>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::UART4>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::UART5>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM6>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM7>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel1>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel2>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel3>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel4_5>() __attribute__ ((weak, alias ("unused_interrupt")));

typedef void (*vector_t)();

vector_t vectors[] __attribute__((section(".vectors"))) = {
	(vector_t)0x20004ffc,
	entry,
	interrupt<Interrupt::NMI>,
	interrupt<Interrupt::HardFault>,
	interrupt<Interrupt::MemManage>,
	interrupt<Interrupt::BusFault>,
	interrupt<Interrupt::UsageFault>,
	0,
	0,
	0,
	0,
	interrupt<Interrupt::SVCall>,
	0,
	0,
	interrupt<Interrupt::PendSV>,
	interrupt<Interrupt::SysTick>,
	interrupt<Interrupt::WWDG>,
	interrupt<Interrupt::PVD>,
	interrupt<Interrupt::TAMPER>,
	interrupt<Interrupt::RTC>,
	interrupt<Interrupt::FLASH>,
	interrupt<Interrupt::RCC>,
	interrupt<Interrupt::EXTI0>,
	interrupt<Interrupt::EXTI1>,
	interrupt<Interrupt::EXTI2>,
	interrupt<Interrupt::EXTI3>,
	interrupt<Interrupt::EXTI4>,
	interrupt<Interrupt::DMA1_Channel1>,
	interrupt<Interrupt::DMA1_Channel2>,
	interrupt<Interrupt::DMA1_Channel3>,
	interrupt<Interrupt::DMA1_Channel4>,
	interrupt<Interrupt::DMA1_Channel5>,
	interrupt<Interrupt::DMA1_Channel6>,
	interrupt<Interrupt::DMA1_Channel7>,
	interrupt<Interrupt::ADC1_2>,
	interrupt<Interrupt::USB_HP_CAN_TX>,
	interrupt<Interrupt::USB_LP_CAN_RX0>,
	interrupt<Interrupt::CAN_RX1>,
	interrupt<Interrupt::CAN_SCE>,
	interrupt<Interrupt::EXTI9_5>,
	interrupt<Interrupt::TIM1_BRK>,
	interrupt<Interrupt::TIM1_UP>,
	interrupt<Interrupt::TIM1_TRG_COM>,
	interrupt<Interrupt::TIM1_CC>,
	interrupt<Interrupt::TIM2>,
	interrupt<Interrupt::TIM3>,
	interrupt<Interrupt::TIM4>,
	interrupt<Interrupt::I2C1_EV>,
	interrupt<Interrupt::I2C1_ER>,
	interrupt<Interrupt::I2C2_EV>,
	interrupt<Interrupt::I2C2_ER>,
	interrupt<Interrupt::SPI1>,
	interrupt<Interrupt::SPI2>,
	interrupt<Interrupt::USART1>,
	interrupt<Interrupt::USART2>,
	interrupt<Interrupt::USART3>,
	interrupt<Interrupt::EXTI15_10>,
	interrupt<Interrupt::RTCAlarm>,
	interrupt<Interrupt::USBWakeup>,
	interrupt<Interrupt::TIM8_BRK>,
	interrupt<Interrupt::TIM8_UP>,
	interrupt<Interrupt::TIM8_TRG_COM>,
	interrupt<Interrupt::TIM8_CC>,
	interrupt<Interrupt::ADC3>,
	interrupt<Interrupt::FSMC>,
	interrupt<Interrupt::SDIO>,
	interrupt<Interrupt::TIM5>,
	interrupt<Interrupt::SPI3>,
	interrupt<Interrupt::UART4>,
	interrupt<Interrupt::UART5>,
	interrupt<Interrupt::TIM6>,
	interrupt<Interrupt::TIM7>,
	interrupt<Interrupt::DMA2_Channel1>,
	interrupt<Interrupt::DMA2_Channel2>,
	interrupt<Interrupt::DMA2_Channel3>,
	interrupt<Interrupt::DMA2_Channel4_5>,
	0, // 60
	0, // 61
	0, // 62
	0, // 63
	0, // 64
	0, // 65
	0, // 66
	0, // 67
	0, // 68
	0, // 69
	0, // 70
	0, // 71
	0, // 72
	0, // 73
	0, // 74
	0, // 75
	0, // 76
	interrupt<(Interrupt::IRQ)77>, // 77
};
<commit_msg>Removed temporary entries from vector table.<commit_after>#include "interrupt.h"

namespace Interrupt {
	MFP mf_vectors[16 + NUM_IRQs];
};

void entry();

void member_function_interrupt_gate() {
	uint32_t interrupt_num;
	asm ("mrs %0, ipsr" : "=r" (interrupt_num));

	Interrupt::mf_vectors[interrupt_num].func_p(Interrupt::mf_vectors[interrupt_num].instance_p);
}

extern "C" void unused_interrupt() {
	member_function_interrupt_gate();
	//while(1);
}

template<> void interrupt<Interrupt::NMI>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::HardFault>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::MemManage>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::BusFault>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::UsageFault>()      __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SVCall>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::PendSV>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SysTick>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::WWDG>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::PVD>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TAMPER>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::RTC>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::FLASH>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::RCC>()             __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI0>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI1>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI2>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI3>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI4>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel1>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel2>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel3>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel4>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel5>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel6>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA1_Channel7>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::ADC1_2>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USB_HP_CAN_TX>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USB_LP_CAN_RX0>()  __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::CAN_RX1>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::CAN_SCE>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI9_5>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_BRK>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_UP>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_TRG_COM>()    __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM1_CC>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM2>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM3>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM4>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C1_EV>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C1_ER>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C2_EV>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::I2C2_ER>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SPI1>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SPI2>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USART1>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USART2>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USART3>()          __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::EXTI15_10>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::RTCAlarm>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::USBWakeup>()       __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_BRK>()        __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_UP>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_TRG_COM>()    __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM8_CC>()         __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::ADC3>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::FSMC>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SDIO>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM5>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::SPI3>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::UART4>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::UART5>()           __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM6>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::TIM7>()            __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel1>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel2>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel3>()   __attribute__ ((weak, alias ("unused_interrupt")));
template<> void interrupt<Interrupt::DMA2_Channel4_5>() __attribute__ ((weak, alias ("unused_interrupt")));

typedef void (*vector_t)();

vector_t vectors[] __attribute__((section(".vectors"))) = {
	(vector_t)0x20004ffc,
	entry,
	interrupt<Interrupt::NMI>,
	interrupt<Interrupt::HardFault>,
	interrupt<Interrupt::MemManage>,
	interrupt<Interrupt::BusFault>,
	interrupt<Interrupt::UsageFault>,
	0,
	0,
	0,
	0,
	interrupt<Interrupt::SVCall>,
	0,
	0,
	interrupt<Interrupt::PendSV>,
	interrupt<Interrupt::SysTick>,
	interrupt<Interrupt::WWDG>,
	interrupt<Interrupt::PVD>,
	interrupt<Interrupt::TAMPER>,
	interrupt<Interrupt::RTC>,
	interrupt<Interrupt::FLASH>,
	interrupt<Interrupt::RCC>,
	interrupt<Interrupt::EXTI0>,
	interrupt<Interrupt::EXTI1>,
	interrupt<Interrupt::EXTI2>,
	interrupt<Interrupt::EXTI3>,
	interrupt<Interrupt::EXTI4>,
	interrupt<Interrupt::DMA1_Channel1>,
	interrupt<Interrupt::DMA1_Channel2>,
	interrupt<Interrupt::DMA1_Channel3>,
	interrupt<Interrupt::DMA1_Channel4>,
	interrupt<Interrupt::DMA1_Channel5>,
	interrupt<Interrupt::DMA1_Channel6>,
	interrupt<Interrupt::DMA1_Channel7>,
	interrupt<Interrupt::ADC1_2>,
	interrupt<Interrupt::USB_HP_CAN_TX>,
	interrupt<Interrupt::USB_LP_CAN_RX0>,
	interrupt<Interrupt::CAN_RX1>,
	interrupt<Interrupt::CAN_SCE>,
	interrupt<Interrupt::EXTI9_5>,
	interrupt<Interrupt::TIM1_BRK>,
	interrupt<Interrupt::TIM1_UP>,
	interrupt<Interrupt::TIM1_TRG_COM>,
	interrupt<Interrupt::TIM1_CC>,
	interrupt<Interrupt::TIM2>,
	interrupt<Interrupt::TIM3>,
	interrupt<Interrupt::TIM4>,
	interrupt<Interrupt::I2C1_EV>,
	interrupt<Interrupt::I2C1_ER>,
	interrupt<Interrupt::I2C2_EV>,
	interrupt<Interrupt::I2C2_ER>,
	interrupt<Interrupt::SPI1>,
	interrupt<Interrupt::SPI2>,
	interrupt<Interrupt::USART1>,
	interrupt<Interrupt::USART2>,
	interrupt<Interrupt::USART3>,
	interrupt<Interrupt::EXTI15_10>,
	interrupt<Interrupt::RTCAlarm>,
	interrupt<Interrupt::USBWakeup>,
	interrupt<Interrupt::TIM8_BRK>,
	interrupt<Interrupt::TIM8_UP>,
	interrupt<Interrupt::TIM8_TRG_COM>,
	interrupt<Interrupt::TIM8_CC>,
	interrupt<Interrupt::ADC3>,
	interrupt<Interrupt::FSMC>,
	interrupt<Interrupt::SDIO>,
	interrupt<Interrupt::TIM5>,
	interrupt<Interrupt::SPI3>,
	interrupt<Interrupt::UART4>,
	interrupt<Interrupt::UART5>,
	interrupt<Interrupt::TIM6>,
	interrupt<Interrupt::TIM7>,
	interrupt<Interrupt::DMA2_Channel1>,
	interrupt<Interrupt::DMA2_Channel2>,
	interrupt<Interrupt::DMA2_Channel3>,
	interrupt<Interrupt::DMA2_Channel4_5>,
};
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Lukasz Janyst <ljanyst@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Utils/SourceNormalization.h"

#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"

#include <utility>

using namespace clang;

namespace {
///\brief A Lexer that exposes preprocessor directives.
class MinimalPPLexer: public Lexer {
public:
  ///\brief Construct a Lexer from LangOpts and source.
  MinimalPPLexer(const LangOptions &LangOpts, llvm::StringRef source):
    Lexer(SourceLocation(), LangOpts,
          source.begin(), source.begin(), source.end()) {}

  bool inPPDirective() const { return ParsingPreprocessorDirective; }

  ///\brief Lex, forwarding to Lexer::LexFromRawLexer, and keeping track of
  /// preprocessor directives to provide a tok::eod corresponding to a
  /// tok::hash.
  bool Lex(Token& Tok) {
    bool ret = LexFromRawLexer(Tok);
    if (inPPDirective()) {
      // Saw a PP directive; probe for eod to end PP parsing mode.
      if (Tok.is(tok::eod))
        ParsingPreprocessorDirective = false;
    } else {
      if (Tok.is(tok::hash)) {
        // Found a PP directive, request tok::eod to be generated.
        ParsingPreprocessorDirective = true;
      }
    }
    return ret;
  }

  ///\brief Advance to token with given token kind.
  ///
  /// \param Tok - Token to advance.
  /// \param kind - Token kind where to stop lexing.
  /// \return - Result of most recent call to Lex().
  bool AdvanceTo(Token& Tok, tok::TokenKind kind) {
    while (!Lex(Tok)) {
      if (Tok.is(kind))
        return false;
    }
    return true;
  }
};

size_t getFileOffset(const Token& Tok) {
  return Tok.getLocation().getRawEncoding();
}

}

size_t
cling::utils::isUnnamedMacro(llvm::StringRef source,
                             clang::LangOptions& LangOpts) {
  // Find the first token that is not a non-cpp directive nor a comment.
  // If that token is a '{' we have an unnamed macro.

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;
  while (true) {
    bool atEOF = Lex.Lex(Tok);
    const tok::TokenKind kind = Tok.getKind();

    if (kind == tok::l_brace)
      return getFileOffset(Tok);

    if (atEOF)
      return std::string::npos;

    if (Lex.inPPDirective())
      continue; // Skip PP directives.

    if (kind == tok::comment)
      continue; // ignore comments

    return std::string::npos;
  }

  // Empty file?

  return std::string::npos;
}

size_t cling::utils::getWrapPoint(std::string& source,
                                  const clang::LangOptions& LangOpts) {
  // TODO: For future reference.
  // Parser* P = const_cast<clang::Parser*>(m_IncrParser->getParser());
  // Parser::TentativeParsingAction TA(P);
  // TPResult result = P->isCXXDeclarationSpecifier();
  // TA.Revert();
  // return result == TPResult::True();

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;

  //size_t wrapPoint = 0;

  while (true) {
    bool atEOF = Lex.Lex(Tok);
    if (Lex.inPPDirective()) {
      //wrapPoint = getFileOffset(Tok);
      if (atEOF)
        break;
      continue; // Skip PP directives; they just move the wrap point.
    }

    const tok::TokenKind kind = Tok.getKind();

    if (kind == tok::raw_identifier && !Tok.needsCleaning()) {
      StringRef keyword(Tok.getRawIdentifier());
      if (keyword.equals("using")) {
        // FIXME: Using definitions and declarations should be decl extracted.
        // Until we have that, don't wrap them if they are the only input.
        if (Lex.AdvanceTo(Tok, tok::semi)) {
          // EOF while looking for semi. Don't wrap.
          return std::string::npos;
        }
        // There is "more" - let's assume this input consists of a using
        // declaration or definition plus some code that should be wrapped.
        return getFileOffset(Tok);
      }
      if (keyword.equals("extern"))
        return std::string::npos;
      if (keyword.equals("namespace"))
        return std::string::npos;
      if (keyword.equals("template"))
        return std::string::npos;

      // There is something else here that needs to be wrapped.
      return getFileOffset(Tok);
    }

    // FIXME: in the future, continue lexing to extract relevant PP directives;
    // return wrapPoint
    // There is something else here that needs to be wrapped.
    return getFileOffset(Tok);
  }

  // We have only had PP directives; no need to wrap.
  return std::string::npos;
}
<commit_msg>Treat tok::eod as part of the PP directive.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Lukasz Janyst <ljanyst@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Utils/SourceNormalization.h"

#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"

#include <utility>

using namespace clang;

namespace {
///\brief A Lexer that exposes preprocessor directives.
class MinimalPPLexer: public Lexer {
public:
  ///\brief Construct a Lexer from LangOpts and source.
  MinimalPPLexer(const LangOptions &LangOpts, llvm::StringRef source):
    Lexer(SourceLocation(), LangOpts,
          source.begin(), source.begin(), source.end()) {}

  bool inPPDirective() const { return ParsingPreprocessorDirective; }

  ///\brief Lex, forwarding to Lexer::LexFromRawLexer, and keeping track of
  /// preprocessor directives to provide a tok::eod corresponding to a
  /// tok::hash.
  bool Lex(Token& Tok) {
    bool ret = LexFromRawLexer(Tok);
    if (inPPDirective()) {
      // Saw a PP directive; probe for eod to end PP parsing mode.
      if (Tok.is(tok::eod))
        ParsingPreprocessorDirective = false;
    } else {
      if (Tok.is(tok::hash)) {
        // Found a PP directive, request tok::eod to be generated.
        ParsingPreprocessorDirective = true;
      }
    }
    return ret;
  }

  ///\brief Advance to token with given token kind.
  ///
  /// \param Tok - Token to advance.
  /// \param kind - Token kind where to stop lexing.
  /// \return - Result of most recent call to Lex().
  bool AdvanceTo(Token& Tok, tok::TokenKind kind) {
    while (!Lex(Tok)) {
      if (Tok.is(kind))
        return false;
    }
    return true;
  }
};

size_t getFileOffset(const Token& Tok) {
  return Tok.getLocation().getRawEncoding();
}

}

size_t
cling::utils::isUnnamedMacro(llvm::StringRef source,
                             clang::LangOptions& LangOpts) {
  // Find the first token that is not a non-cpp directive nor a comment.
  // If that token is a '{' we have an unnamed macro.

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;
  while (true) {
    bool atEOF = Lex.Lex(Tok);
    const tok::TokenKind kind = Tok.getKind();

    if (kind == tok::l_brace)
      return getFileOffset(Tok);

    if (atEOF)
      return std::string::npos;

    if (Lex.inPPDirective() || Tok.is(tok::eod))
      continue; // Skip PP directives.

    if (kind == tok::comment)
      continue; // ignore comments

    return std::string::npos;
  }

  // Empty file?

  return std::string::npos;
}

size_t cling::utils::getWrapPoint(std::string& source,
                                  const clang::LangOptions& LangOpts) {
  // TODO: For future reference.
  // Parser* P = const_cast<clang::Parser*>(m_IncrParser->getParser());
  // Parser::TentativeParsingAction TA(P);
  // TPResult result = P->isCXXDeclarationSpecifier();
  // TA.Revert();
  // return result == TPResult::True();

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;

  //size_t wrapPoint = 0;

  while (true) {
    bool atEOF = Lex.Lex(Tok);
    if (Lex.inPPDirective() || Tok.is(tok::eod)) {
      //wrapPoint = getFileOffset(Tok);
      if (atEOF)
        break;
      continue; // Skip PP directives; they just move the wrap point.
    }

    const tok::TokenKind kind = Tok.getKind();

    if (kind == tok::raw_identifier && !Tok.needsCleaning()) {
      StringRef keyword(Tok.getRawIdentifier());
      if (keyword.equals("using")) {
        // FIXME: Using definitions and declarations should be decl extracted.
        // Until we have that, don't wrap them if they are the only input.
        if (Lex.AdvanceTo(Tok, tok::semi)) {
          // EOF while looking for semi. Don't wrap.
          return std::string::npos;
        }
        // There is "more" - let's assume this input consists of a using
        // declaration or definition plus some code that should be wrapped.
        return getFileOffset(Tok);
      }
      if (keyword.equals("extern"))
        return std::string::npos;
      if (keyword.equals("namespace"))
        return std::string::npos;
      if (keyword.equals("template"))
        return std::string::npos;

      // There is something else here that needs to be wrapped.
      return getFileOffset(Tok);
    }

    // FIXME: in the future, continue lexing to extract relevant PP directives;
    // return wrapPoint
    // There is something else here that needs to be wrapped.
    return getFileOffset(Tok);
  }

  // We have only had PP directives; no need to wrap.
  return std::string::npos;
}
<|endoftext|>


<commit_before>//
//  ImageCompressorApp.cpp
//  ImageCompressor
//
//  Created by Jean-Pierre Mouilleseaux on 16 Mar 2015.
//  Copyright 2015 Chorded Constructions. All rights reserved.
//

#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"
#include "cinder/Log.h"

#include "Cinder-DDS.h"

using namespace ci;
using namespace ci::app;
using namespace Cinder::DDS;
using namespace std;

static const std::string sVertexShaderPassThrough = R"(
    #version 150
    uniform mat4 ciModelViewProjection;

    in vec4 ciPosition;
    in vec2	ciTexCoord0;

    out vec2 vTexCoord0;

    void main() {
        vTexCoord0 = ciTexCoord0;
        gl_Position = ciModelViewProjection * ciPosition;
    }
)";

static const std::string sFragmentShaderColorSpaceConversion = R"(
    #version 150
    uniform sampler2D image;
    uniform bool hasAlpha;

    in vec2 vTexCoord0;

    out vec4 oFragColor;

    void main() {
        vec4 color = texture(image, vTexCoord0);

        // component encoding and order differs on presence of alpha
        float y, co, cg, a;
        if (hasAlpha) {
            co = color.x - (0.5 * 256.0 / 255.0);
            cg = color.y - (0.5 * 256.0 / 255.0);
            a = color.z;
            y = color.w;
        } else {
            co = color.x - (0.5 * 256.0 / 255.0);
            y = color.y;
            cg = color.z - (0.5 * 256.0 / 255.0);
            a = 1.0;
        }
        float r = y + co - cg;
        float g = y + cg;
        float b = y - co - cg;
        vec4 result = vec4(r, g, b, a);

        oFragColor = result;
    }
)";

class ImageCompressorApp : public App {
public:
	void setup() override;
	void draw() override;

private:
    Surface8uRef mSurface;
    gl::Texture2dRef mSourceTexture;
    gl::Texture2dRef mResultTexture;
    ci::gl::FboRef mFBO;
    ci::gl::GlslProgRef mShader;
};

void ImageCompressorApp::setup() {
    // grab the source
    try {
        mSurface = Surface::create(loadImage(loadAsset("grad-cutout.png")));
    } catch (ci::Exception& e) {
        CI_LOG_EXCEPTION("unable to create surface", e);
        quit();
    }
    mSourceTexture = gl::Texture::create(*mSurface);

    // convert to a DXT compressed DDS file buffer
    CompressionFormat format = CompressionFormat::YCoCg_DXT5;
    const Buffer buffer = DDSConvert(mSurface, format);

    // create a texture from DDS file buffer
    try {
        mResultTexture = gl::Texture2d::createFromDds(DataSourceBuffer::create(buffer));
    } catch (ci::Exception& e) {
        CI_LOG_EXCEPTION("failed to create texture from DDS file", e);
        quit();
    }

    // handle color space conversion if using YCoCg_DXT5
    if (format == CompressionFormat::YCoCg_DXT5) {
        // create FBO
        mFBO = gl::Fbo::create(mResultTexture->getWidth(), mResultTexture->getHeight());

        // create color space conversion shader
        try {
            mShader = gl::GlslProg::create(sVertexShaderPassThrough, sFragmentShaderColorSpaceConversion);
        } catch (gl::GlslProgCompileExc& e) {
            CI_LOG_EXCEPTION("failed to compile shader", e);
            quit();
        } catch (ci::Exception& e) {
            CI_LOG_EXCEPTION("failed to create shader", e);
            quit();
        }

        // run texture through shader into FBO
        gl::ScopedMatrices matricies;
        gl::ScopedViewport viewport(ivec2(0), mFBO->getSize());
        gl::ScopedFramebuffer fbo(mFBO);

        gl::setMatricesWindow(mFBO->getSize());
        gl::color(Color::white());

        gl::ScopedTextureBind texture(mResultTexture);
        gl::ScopedGlslProg shader(mShader);

        mShader->uniform("image", 0);
        mShader->uniform("hasAlpha", mSurface->hasAlpha());
        gl::drawSolidRect(mResultTexture->getBounds());

        // pull texture out of the FBO
        mResultTexture = mFBO->getColorTexture();
    }

    // denote the texture as vertically flipped
    mResultTexture->setTopDown();

    if (mSurface->hasAlpha()) {
        gl::enableAlphaBlending();
    }
}

void ImageCompressorApp::draw() {
    gl::clear();

    if (!mSourceTexture) {
        return;
    }
    gl::draw(mSourceTexture);

    if (!mResultTexture) {
        return;
    }
    gl::pushMatrices(); {
        gl::translate(mSourceTexture->getWidth(), 0);
        gl::draw(mResultTexture);
    } gl::popMatrices();
}

CINDER_APP(ImageCompressorApp, RendererGl, [](App::Settings* settings) {
    settings->setHighDensityDisplayEnabled();
    settings->prepareWindow(Window::Format().size(1024, 512));
})
<commit_msg>use new texture hasAlpha() accessor<commit_after>//
//  ImageCompressorApp.cpp
//  ImageCompressor
//
//  Created by Jean-Pierre Mouilleseaux on 16 Mar 2015.
//  Copyright 2015 Chorded Constructions. All rights reserved.
//

#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"
#include "cinder/Log.h"

#include "Cinder-DDS.h"

using namespace ci;
using namespace ci::app;
using namespace Cinder::DDS;
using namespace std;

static const std::string sVertexShaderPassThrough = R"(
    #version 150
    uniform mat4 ciModelViewProjection;

    in vec4 ciPosition;
    in vec2	ciTexCoord0;

    out vec2 vTexCoord0;

    void main() {
        vTexCoord0 = ciTexCoord0;
        gl_Position = ciModelViewProjection * ciPosition;
    }
)";

static const std::string sFragmentShaderColorSpaceConversion = R"(
    #version 150
    uniform sampler2D image;
    uniform bool hasAlpha;

    in vec2 vTexCoord0;

    out vec4 oFragColor;

    void main() {
        vec4 color = texture(image, vTexCoord0);

        // component encoding and order differs on presence of alpha
        float y, co, cg, a;
        if (hasAlpha) {
            co = color.x - (0.5 * 256.0 / 255.0);
            cg = color.y - (0.5 * 256.0 / 255.0);
            a = color.z;
            y = color.w;
        } else {
            co = color.x - (0.5 * 256.0 / 255.0);
            y = color.y;
            cg = color.z - (0.5 * 256.0 / 255.0);
            a = 1.0;
        }
        float r = y + co - cg;
        float g = y + cg;
        float b = y - co - cg;
        vec4 result = vec4(r, g, b, a);

        oFragColor = result;
    }
)";

class ImageCompressorApp : public App {
public:
	void setup() override;
	void draw() override;

private:
    Surface8uRef mSurface;
    gl::Texture2dRef mSourceTexture;
    gl::Texture2dRef mResultTexture;
    ci::gl::FboRef mFBO;
    ci::gl::GlslProgRef mShader;
};

void ImageCompressorApp::setup() {
    // grab the source
    try {
        mSurface = Surface::create(loadImage(loadAsset("grad-cutout.png")));
    } catch (ci::Exception& e) {
        CI_LOG_EXCEPTION("unable to create surface", e);
        quit();
    }
    mSourceTexture = gl::Texture::create(*mSurface);

    // convert to a DXT compressed DDS file buffer
    CompressionFormat format = CompressionFormat::YCoCg_DXT5;
    const Buffer buffer = DDSConvert(mSurface, format);

    // create a texture from DDS file buffer
    try {
        mResultTexture = gl::Texture2d::createFromDds(DataSourceBuffer::create(buffer));
    } catch (ci::Exception& e) {
        CI_LOG_EXCEPTION("failed to create texture from DDS file", e);
        quit();
    }

    // handle color space conversion if using YCoCg_DXT5
    if (format == CompressionFormat::YCoCg_DXT5) {
        // create FBO
        mFBO = gl::Fbo::create(mResultTexture->getWidth(), mResultTexture->getHeight());

        // create color space conversion shader
        try {
            mShader = gl::GlslProg::create(sVertexShaderPassThrough, sFragmentShaderColorSpaceConversion);
        } catch (gl::GlslProgCompileExc& e) {
            CI_LOG_EXCEPTION("failed to compile shader", e);
            quit();
        } catch (ci::Exception& e) {
            CI_LOG_EXCEPTION("failed to create shader", e);
            quit();
        }

        // run texture through shader into FBO
        gl::ScopedMatrices matricies;
        gl::ScopedViewport viewport(ivec2(0), mFBO->getSize());
        gl::ScopedFramebuffer fbo(mFBO);

        gl::setMatricesWindow(mFBO->getSize());
        gl::color(Color::white());

        gl::ScopedTextureBind texture(mResultTexture);
        gl::ScopedGlslProg shader(mShader);

        mShader->uniform("image", 0);
        mShader->uniform("hasAlpha", mResultTexture->hasAlpha());
        gl::drawSolidRect(mResultTexture->getBounds());

        // pull texture out of the FBO
        mResultTexture = mFBO->getColorTexture();
    }

    // denote the texture as vertically flipped
    mResultTexture->setTopDown();

    if (mResultTexture->hasAlpha()) {
        gl::enableAlphaBlending();
    }
}

void ImageCompressorApp::draw() {
    gl::clear();

    if (!mSourceTexture) {
        return;
    }
    gl::draw(mSourceTexture);

    if (!mResultTexture) {
        return;
    }
    gl::pushMatrices(); {
        gl::translate(mSourceTexture->getWidth(), 0);
        gl::draw(mResultTexture);
    } gl::popMatrices();
}

CINDER_APP(ImageCompressorApp, RendererGl, [](App::Settings* settings) {
    settings->setHighDensityDisplayEnabled();
    settings->prepareWindow(Window::Format().size(1024, 512));
})
<|endoftext|>