<commit_before>//===- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation -==//
//
// This file implements the generic AliasAnalysis interface which is used as the
// common interface used by all clients and implementations of alias analysis.
//
// This file also implements the default version of the AliasAnalysis interface
// that is to be used when no other implementation is specified.  This does some
// simple tests that detect obvious cases: two different global pointers cannot
// alias, a global cannot alias a malloc, two different mallocs cannot alias,
// etc.
//
// This alias analysis implementation really isn't very good for anything, but
// it is very fast, and makes a nice clean default implementation.  Because it
// handles lots of little corner cases, other, more complex, alias analysis
// implementations may choose to rely on this pass to resolve these simple and
// easy cases.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/BasicBlock.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/iMemory.h"
#include "llvm/Constants.h"
#include "llvm/GlobalValue.h"
#include "llvm/DerivedTypes.h"

// Register the AliasAnalysis interface, providing a nice name to refer to.
static RegisterAnalysisGroup<AliasAnalysis> X("Alias Analysis");

// CanModify - Define a little visitor class that is used to check to see if
// arbitrary chunks of code can modify a specified pointer.
//
namespace {
  struct CanModify : public InstVisitor<CanModify, bool> {
    const AliasAnalysis &AA;
    const Value *Ptr;

    CanModify(const AliasAnalysis *aa, const Value *ptr)
      : AA(*aa), Ptr(ptr) {}

    bool visitInvokeInst(InvokeInst &II) {
      return AA.canInvokeModify(II, Ptr);
    }
    bool visitCallInst(CallInst &CI) {
      return AA.canCallModify(CI, Ptr);
    }
    bool visitStoreInst(StoreInst &SI) {
      return AA.alias(Ptr, SI.getOperand(1));
    }

    // Other instructions do not alias anything.
    bool visitInstruction(Instruction &I) { return false; }
  };
}

// AliasAnalysis destructor: DO NOT move this to the header file for
// AliasAnalysis or else clients of the AliasAnalysis class may not depend on
// the AliasAnalysis.o file in the current .a file, causing alias analysis
// support to not be included in the tool correctly!
//
AliasAnalysis::~AliasAnalysis() {}

/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the value pointed to by Ptr.
///
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &bb,
                                        const Value *Ptr) const {
  CanModify CM(this, Ptr);
  BasicBlock &BB = const_cast<BasicBlock&>(bb);

  for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
    if (CM.visit(I))        // Check every instruction in the basic block...
      return true;

  return false;
}

/// canInstructionRangeModify - Return true if it is possible for the execution
/// of the specified instructions to modify the value pointed to by Ptr.  The
/// instructions to consider are all of the instructions in the range of [I1,I2]
/// INCLUSIVE.  I1 and I2 must be in the same basic block.
///
bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1,
                                              const Instruction &I2,
                                              const Value *Ptr) const {
  assert(I1.getParent() == I2.getParent() &&
         "Instructions not in same basic block!");
  CanModify CM(this, Ptr);
  BasicBlock::iterator I = const_cast<Instruction*>(&I1);
  BasicBlock::iterator E = const_cast<Instruction*>(&I2);
  ++E;  // Convert from inclusive to exclusive range.

  for (; I != E; ++I)
    if (CM.visit(I))        // Check every instruction in the basic block...
      return true;

  return false;
}

//===----------------------------------------------------------------------===//
// BasicAliasAnalysis Pass Implementation
//===----------------------------------------------------------------------===//
//
// Because of the way .a files work, the implementation of the
// BasicAliasAnalysis class MUST be in the AliasAnalysis file itself, or else we
// run the risk of AliasAnalysis being used, but the default implementation not
// being linked into the tool that uses it.  As such, we register and implement
// the class here.
//
namespace {
  // Register this pass...
  RegisterOpt<BasicAliasAnalysis>
  X("basicaa", "Basic Alias Analysis (default AA impl)");

  // Declare that we implement the AliasAnalysis interface
  RegisterAnalysisGroup<AliasAnalysis, BasicAliasAnalysis, true> Y;
}  // End of anonymous namespace

// hasUniqueAddress - Return true if the
static inline bool hasUniqueAddress(const Value *V) {
  return isa<GlobalValue>(V) || isa<MallocInst>(V) || isa<AllocaInst>(V);
}

AliasAnalysis::Result BasicAliasAnalysis::alias(const Value *V1,
                                                const Value *V2) const {
  // Strip off constant pointer refs if they exist
  if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(V1))
    V1 = CPR->getValue();
  if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(V2))
    V2 = CPR->getValue();

  // Are we checking for alias of the same value?
  if (V1 == V2) return MustAlias;

  if (!isa<PointerType>(V1->getType()) || !isa<PointerType>(V2->getType()))
    return NoAlias;  // Scalars cannot alias each other

  bool V1Unique = hasUniqueAddress(V1);
  bool V2Unique = hasUniqueAddress(V2);

  if (V1Unique && V2Unique)
    return NoAlias;         // Can't alias if they are different unique values

  if ((V1Unique && isa<ConstantPointerNull>(V2)) ||
      (V2Unique && isa<ConstantPointerNull>(V1)))
    return NoAlias;         // Unique values don't alias null

  // TODO: Handle getelementptr with nonzero offset

  return MayAlias;
}
<commit_msg>* Add capability to recognize alias properties of the following common cases:   - A[c1] cannot alias A[c2] where constants c1 != c2   - A[i] cannot alias B[j] if A & B are provably different arrays<commit_after>//===- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation -==//
//
// This file implements the generic AliasAnalysis interface which is used as the
// common interface used by all clients and implementations of alias analysis.
//
// This file also implements the default version of the AliasAnalysis interface
// that is to be used when no other implementation is specified.  This does some
// simple tests that detect obvious cases: two different global pointers cannot
// alias, a global cannot alias a malloc, two different mallocs cannot alias,
// etc.
//
// This alias analysis implementation really isn't very good for anything, but
// it is very fast, and makes a nice clean default implementation.  Because it
// handles lots of little corner cases, other, more complex, alias analysis
// implementations may choose to rely on this pass to resolve these simple and
// easy cases.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/BasicBlock.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/iMemory.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/GlobalValue.h"
#include "llvm/DerivedTypes.h"

// Register the AliasAnalysis interface, providing a nice name to refer to.
static RegisterAnalysisGroup<AliasAnalysis> X("Alias Analysis");

// CanModify - Define a little visitor class that is used to check to see if
// arbitrary chunks of code can modify a specified pointer.
//
namespace {
  struct CanModify : public InstVisitor<CanModify, bool> {
    const AliasAnalysis &AA;
    const Value *Ptr;

    CanModify(const AliasAnalysis *aa, const Value *ptr)
      : AA(*aa), Ptr(ptr) {}

    bool visitInvokeInst(InvokeInst &II) {
      return AA.canInvokeModify(II, Ptr);
    }
    bool visitCallInst(CallInst &CI) {
      return AA.canCallModify(CI, Ptr);
    }
    bool visitStoreInst(StoreInst &SI) {
      return AA.alias(Ptr, SI.getOperand(1));
    }

    // Other instructions do not alias anything.
    bool visitInstruction(Instruction &I) { return false; }
  };
}

// AliasAnalysis destructor: DO NOT move this to the header file for
// AliasAnalysis or else clients of the AliasAnalysis class may not depend on
// the AliasAnalysis.o file in the current .a file, causing alias analysis
// support to not be included in the tool correctly!
//
AliasAnalysis::~AliasAnalysis() {}

/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the value pointed to by Ptr.
///
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &bb,
                                        const Value *Ptr) const {
  CanModify CM(this, Ptr);
  BasicBlock &BB = const_cast<BasicBlock&>(bb);

  for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
    if (CM.visit(I))        // Check every instruction in the basic block...
      return true;

  return false;
}

/// canInstructionRangeModify - Return true if it is possible for the execution
/// of the specified instructions to modify the value pointed to by Ptr.  The
/// instructions to consider are all of the instructions in the range of [I1,I2]
/// INCLUSIVE.  I1 and I2 must be in the same basic block.
///
bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1,
                                              const Instruction &I2,
                                              const Value *Ptr) const {
  assert(I1.getParent() == I2.getParent() &&
         "Instructions not in same basic block!");
  CanModify CM(this, Ptr);
  BasicBlock::iterator I = const_cast<Instruction*>(&I1);
  BasicBlock::iterator E = const_cast<Instruction*>(&I2);
  ++E;  // Convert from inclusive to exclusive range.

  for (; I != E; ++I)
    if (CM.visit(I))        // Check every instruction in the basic block...
      return true;

  return false;
}

//===----------------------------------------------------------------------===//
// BasicAliasAnalysis Pass Implementation
//===----------------------------------------------------------------------===//
//
// Because of the way .a files work, the implementation of the
// BasicAliasAnalysis class MUST be in the AliasAnalysis file itself, or else we
// run the risk of AliasAnalysis being used, but the default implementation not
// being linked into the tool that uses it.  As such, we register and implement
// the class here.
//
namespace {
  // Register this pass...
  RegisterOpt<BasicAliasAnalysis>
  X("basicaa", "Basic Alias Analysis (default AA impl)");

  // Declare that we implement the AliasAnalysis interface
  RegisterAnalysisGroup<AliasAnalysis, BasicAliasAnalysis, true> Y;
}  // End of anonymous namespace

// hasUniqueAddress - Return true if the
static inline bool hasUniqueAddress(const Value *V) {
  return isa<GlobalValue>(V) || isa<MallocInst>(V) || isa<AllocaInst>(V);
}

static const Value *getUnderlyingObject(const Value *V) {
  if (!isa<PointerType>(V->getType())) return 0;

  // If we are at some type of object... return it.
  if (hasUniqueAddress(V)) return V;

  // Traverse through different addressing mechanisms...
  if (const Instruction *I = dyn_cast<Instruction>(V)) {
    if (isa<CastInst>(I) || isa<GetElementPtrInst>(I))
      return getUnderlyingObject(I->getOperand(0));
  }
  return 0;
}

// alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such
// as array references.  Note that this function is heavily tail recursive.
// Hopefully we have a smart C++ compiler.  :)
//
AliasAnalysis::Result BasicAliasAnalysis::alias(const Value *V1,
                                                const Value *V2) const {
  // Strip off constant pointer refs if they exist
  if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(V1))
    V1 = CPR->getValue();
  if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(V2))
    V2 = CPR->getValue();

  // Are we checking for alias of the same value?
  if (V1 == V2) return MustAlias;

  if ((!isa<PointerType>(V1->getType()) || !isa<PointerType>(V2->getType())) &&
      V1->getType() != Type::LongTy && V2->getType() != Type::LongTy)
    return NoAlias;  // Scalars cannot alias each other

  // Strip off cast instructions...
  if (const Instruction *I = dyn_cast<CastInst>(V1))
    return alias(I->getOperand(0), V2);
  if (const Instruction *I = dyn_cast<CastInst>(V2))
    return alias(I->getOperand(0), V1);

  // If we have two gep instructions with identical indices, return an alias
  // result equal to the alias result of the original pointer...
  //
  if (const GetElementPtrInst *GEP1 = dyn_cast<GetElementPtrInst>(V1))
    if (const GetElementPtrInst *GEP2 = dyn_cast<GetElementPtrInst>(V2))
      if (GEP1->getNumOperands() == GEP2->getNumOperands() &&
          GEP1->getOperand(0)->getType() == GEP2->getOperand(0)->getType()) {
        if (std::equal(GEP1->op_begin()+1, GEP1->op_end(), GEP2->op_begin()+1))
          return alias(GEP1->getOperand(0), GEP2->getOperand(0));

        // If all of the indexes to the getelementptr are constant, but
        // different (well we already know they are different), then we know
        // that there cannot be an alias here if the two base pointers DO alias.
        //
        bool AllConstant = true;
        for (unsigned i = 1, e = GEP1->getNumOperands(); i != e; ++i)
          if (!isa<Constant>(GEP1->getOperand(i)) ||
              !isa<Constant>(GEP2->getOperand(i))) {
            AllConstant = false;
            break;
          }

        // If we are all constant, then look at where the the base pointers
        // alias.  If they are known not to alias, then we are dealing with two
        // different arrays or something, so no alias is possible.  If they are
        // known to be the same object, then we cannot alias because we are
        // indexing into a different part of the object.  As usual, MayAlias
        // doesn't tell us anything.
        //
        if (AllConstant &&
            alias(GEP1->getOperand(0), GEP2->getOperand(1)) != MayAlias)
            return NoAlias;
      }

  // Figure out what objects these things are pointing to if we can...
  const Value *O1 = getUnderlyingObject(V1);
  const Value *O2 = getUnderlyingObject(V2);

  // Pointing at a discernable object?
  if (O1 && O2) {
    // If they are two different objects, we know that we have no alias...
    if (O1 != O2) return NoAlias;

    // If they are the same object, they we can look at the indexes.  If they
    // index off of the object is the same for both pointers, they must alias.
    // If they are provably different, they must not alias.  Otherwise, we can't
    // tell anything.
  } else if (O1 && isa<ConstantPointerNull>(V2)) {
    return NoAlias;                    // Unique values don't alias null
  } else if (O2 && isa<ConstantPointerNull>(V1)) {
    return NoAlias;                    // Unique values don't alias null
  }

  return MayAlias;
}
<|endoftext|>


<commit_before>#include "Platform.hpp"
#include "genome.pb.h"
#include "Brain.hpp"
#include "ProteinEnvironment.hpp"
#include "Neuron.hpp"
#include "Synapse.hpp"
#include "SimpleSpatialSearch.hpp"
#include "BrainPlugins.hpp"
#include "BrainPlugin.hpp"

#define INPUT_NEURONS			100
#define INPUT_REGION_MINX		0.0f
#define INPUT_REGION_MAXX		5.0f
#define INPUT_REGION_MINY		0.0f
#define INPUT_REGION_MAXY		5.0f
#define INPUT_REGION_SPACING	0.01f	//This also implies max input neurons of ((max-min)/spacing)^2
#define INPUT_AXON_SPREAD		0.0f	//The range of axon locations from input neurons
#define DEVELOPMENT_TICKS		10		//How often development neurons are re-evaluated

#include <boost/math/distributions/uniform.hpp>
#include <boost/random.hpp>

namespace Elysia {

/**
 *  @param ProteinEnvironment *proteinMap - a base protein map for the brain
 *
 *	Description:	Creates a new Brain instance using a defined protein map as a base.
 *					Also adds a new spatial search instance, sets the brain's age to 0 and
 *					initializes all requisite brain plugins
**/
Brain::Brain (ProteinEnvironment *proteinMap){
    mProteinMap=proteinMap;
    mSpatialSearch=new SimpleSpatialSearch;
    mAge=0;
	mDevelopmentCounter=0;
	createInputRegion(INPUT_NEURONS);
    makeInitialNeurons();
    BrainPlugins::constructAll(this).swap(mPlugins);
}

void Brain::syncEnvironmentNeurons(unsigned int index, ProteinEnvironment::iterator environmentIterator){
    Elysia::Genome::Effect growEffect=Elysia::Genome::GROW_NEURON;
    float neuronDensity =environmentIterator.getProteinDensity(growEffect);
    BoundingBox3f3f bounds = environmentIterator.getBoundingBox();
    float area = bounds.across().x*bounds.across().y;
    float expectedNumNeurons=neuronDensity*area;
    boost::minstd_rand randGen(1+index);//needs to be >0
    boost::uniform_real<> uni_dist(0.0f,1.0f);
    boost::variate_generator<boost::minstd_rand, boost::uniform_real<> > uniform(randGen,uni_dist);
    if (expectedNumNeurons-floor(expectedNumNeurons)<uniform()) {
        expectedNumNeurons=ceil(expectedNumNeurons);
    }else {
        expectedNumNeurons=floor(expectedNumNeurons);
    }
    int numNeurons=(unsigned int)expectedNumNeurons;
    if (numNeurons<mNumNeurons[index]) {
        //FIXME: do we want to delete excess neurons
    }
    for (int n=mNumNeurons[index];n<numNeurons;++n) {
        this->addNeuron(bounds, environmentIterator.retrieveGene(growEffect));
    }
    if (mNumNeurons[index]!=numNeurons) {
        fprintf(stderr,"The index count isn't equal to the sync count:\nthis could happen if a neuron lies at the exact edge of a lobe,\nso don't panic, but verify that this is indeed the case\nand the wrong count got updated for that neuron");
    }
}

void Brain::makeInitialNeurons() {
    unsigned int index=0;
    for (ProteinEnvironment::iterator i=mProteinMap->begin();
         i!=mProteinMap->end();
         ++i,++index) {
        mNumNeurons[i.uid()]=0;
        syncEnvironmentNeurons(index,i);
        //FIXME add numNeurons to the count in this protein zone so we can add/remove more later
    }
}

Neuron * Brain::addNeuron(const BoundingBox3f3f&generationArea, const Genome::Gene&gene) {
    Vector3f v = generationArea.min();
    v.x+=generationArea.across().x*(rand()/(double)RAND_MAX);
    v.y+=generationArea.across().y*(rand()/(double)RAND_MAX);
	v.z=0;	 //Fixing z to 0 for now.
    //v.z+=generationArea.across().z*(rand()/(double)RAND_MAX);
	Neuron *n = new Neuron(this, 2, 3, 4, 1, 1, v, gene);
    mAllNeurons.insert(n);
    return n;
}

/**
 *	Description:	One "tick" of the brain simulation code, where the following occurs:
 *					 - processNeuron() called
 *					 - processSynapes() called
 *					 - increments the current time in the simulation
 *					 - ages the brain
 *					 - updates all the plugins for this brain
**/
void Brain::tick(){
	processNeuron();
	processSynapse();
	//developAllNeurons();
    ++mCurTime;
	++mDevelopmentCounter;
	if(mDevelopmentCounter%10 == 0)this->processDevelopment();
    mAge+=1.0e-6;//fixme this is probably not correct: we probably need genes to do this
    if (mAge>1.0) mAge=1.0;
    for(std::vector<BrainPlugin*>::iterator i=mPlugins.begin(),ie=mPlugins.end();i!=ie;++i) {
        (*i)->update();
    }
}

void Brain::developAllNeurons(){
	for(std::set<Neuron*>::iterator i=mAllNeurons.begin(),ie=mAllNeurons.end();i!=ie;++i){
		(*i)->developSynapse((*i)->getActivityStats());
	}
}

/**
 *	Description:	Updates all neurons in the neuron list for this brain, then clears the list of
 *					active neurons
**/
void Brain::processNeuron(){
	for (std::list<Neuron*>::iterator i=mActiveNeurons.begin(),ie=mActiveNeurons.end();
         i!=ie;
		 ++i) {
        (*i)->tick();
	}
	mActiveNeurons.clear();
}

/**
 *	Description:	Iterates through brain's associates synapses and updates all of them using
 *					the Synapse class residualFire() method
**/
void Brain::processSynapse(){
    std::list<Synapse*>::iterator j,i=mActiveSynapses.begin(),ie=mActiveSynapses.end();
	while (i!=ie) {
        std::list<Synapse*>::iterator j=i++;
        (*j)->residualFire();
	}
}

/**
 *	@param Synapse *inactiveSynapse - synapse to remove
 *
 *	Description:	Removes a synapse from the synapse list and updates it.
**/
void Brain::inactivateSynapse(Synapse *inactiveSynapse){
	mActiveSynapses.erase(inactiveSynapse->mWhere);
	inactiveSynapse->mWhere=activeSynapseListSentinel();
}

void Brain::deleteSynapse(Synapse *deletedSynapse){
	//mActiveSynapses.erase(deletedSynapse->mWhere);
}

/**
 *	@param Neuron *inactiveNeuron - an inactive neuron to remove
 *
 *	Description:	Removes an unused neuron from the neuron list and updates
**/
void Brain::inactivateNeuron(Neuron *inactiveNeuron){
	mActiveNeurons.erase(inactiveNeuron->mWhere);
	inactiveNeuron->mWhere=activeNeuronListSentinel();
}

void Brain::deleteNeuron(Neuron *deletedNeuron){
	//mAllNeurons.erase(deletedNeuron->mWhere);
}

/**
 *	@param Synapse *activeSynapse - a synapse to activate
 *	@return	the beginning element of the active synapses list for this brain
 *
 *	Description:	Adds a new synapse to the brain (at front of active synapse list)
 *					and returns the front element of the list
**/
std::list<Synapse *>::iterator Brain::activateSynapse(Synapse *activeSynapse){
    mActiveSynapses.push_front(activeSynapse);
    return mActiveSynapses.begin();
}
/**
 *	@param Neuron *activeNeuron - a neuron to activate
 *	@return	the beginning element of the active neuron list for this brain
 *
 *	Description:	Adds a new neuron to the brain (at front of active neuron list)
 *					and returns the front element of the list
**/
std::list<Neuron *>::iterator Brain::activateNeuron(Neuron *activeNeuron){
  activeNeuron->mActivity=5.0f;
  mActiveNeurons.push_front(activeNeuron);
  return mActiveNeurons.begin();
}

/**
 *	Brain destructor
**/
Brain::~Brain() {
	for(std::set<Neuron*>::iterator i=mAllNeurons.begin(),ie=mAllNeurons.end();i!=ie;++i){
		delete *i;
	}
    delete mSpatialSearch;
    delete mProteinMap;
    for (std::vector<BrainPlugin*>::iterator i=mPlugins.begin(),ie=mPlugins.end();i!=ie;++i) {
        delete *i;
    }
}

Neuron* Brain::createInputNeuron(float x, float y, float z, float spread){
	Genome::Gene gene;
    Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
    Genome::TemporalBoundingBox *dendritebb=gene.add_bounds();
    sourcebb->set_minx(x-spread);
    sourcebb->set_miny(y-spread);
    sourcebb->set_minz(0);
    sourcebb->set_maxx(x+spread);
    sourcebb->set_maxy(y+spread);
    sourcebb->set_maxz(0);

    dendritebb->set_minx(0);
    dendritebb->set_miny(0);
    dendritebb->set_minz(0);
    dendritebb->set_maxx(0);
    dendritebb->set_maxy(0);
    dendritebb->set_maxz(0);

	Vector3f v;
	v.x = x;
	v.y = y;
	v.z = z;
	Neuron *n;
	this->mAllNeurons.insert(n = new Neuron(this, 0, 0, 0, 1, 1, v,gene));
	this->mDevelopingNeurons.insert(n);
	return n;
}

void Brain::createInputRegion(int neurons){
	//At present, reserved location of input lobe is <0,0,0> to <5,5,0> neurons are added at 0.01 increments
	float minx = INPUT_REGION_MINX;
	float maxx = INPUT_REGION_MAXX;
	float miny = INPUT_REGION_MINY;
	float maxy = INPUT_REGION_MAXY;
	float spacing = INPUT_REGION_SPACING;
	float spread = INPUT_AXON_SPREAD;

	if(neurons > (maxx-minx)*(maxy-miny)/spacing){
		assert(this);
	}
	Neuron* n;
	float x=minx;
	float y=miny;

	for(int i=0;i<neurons;i++){
		n = createInputNeuron(x,y,0,spread);
		mInputNeurons.push_back(n);
		x += spacing;
		if(x >= maxx){
			x = minx;
			y += spacing;
		}
	}
}

void Brain::fireInputNeuron(int neuronNumber){
	Neuron* n= mInputNeurons[neuronNumber];
	n->setActivity(5);
	this -> activateNeuron(n);
	//printf("input");
}

void Brain::processDevelopment(){
	for(std::set<Neuron*>::iterator i=mAllNeurons.begin(),ie=mAllNeurons.end();i!=ie;++i){
		(*i)->tick();
	}
}

/**
 * @return the bounds of all genes in the brain, i.e. where the farthest neurons may spout
 */
BoundingBox3f3f Brain::getBounds()const{

//    return BoundingBox3f3f(Vector3f(0,00,00),Vector3f(1000,1000,1000));
    return mProteinMap->getBounds();
}

}

<commit_msg>Fixed problem with Neuron destruction by making sure that the neuron was actually in the active list before erasing it from the active list. Same with synapses<commit_after>#include "Platform.hpp"
#include "genome.pb.h"
#include "Brain.hpp"
#include "ProteinEnvironment.hpp"
#include "Neuron.hpp"
#include "Synapse.hpp"
#include "SimpleSpatialSearch.hpp"
#include "BrainPlugins.hpp"
#include "BrainPlugin.hpp"

#define INPUT_NEURONS			100
#define INPUT_REGION_MINX		0.0f
#define INPUT_REGION_MAXX		5.0f
#define INPUT_REGION_MINY		0.0f
#define INPUT_REGION_MAXY		5.0f
#define INPUT_REGION_SPACING	0.01f	//This also implies max input neurons of ((max-min)/spacing)^2
#define INPUT_AXON_SPREAD		0.0f	//The range of axon locations from input neurons
#define DEVELOPMENT_TICKS		10		//How often development neurons are re-evaluated

#include <boost/math/distributions/uniform.hpp>
#include <boost/random.hpp>

namespace Elysia {

/**
 *  @param ProteinEnvironment *proteinMap - a base protein map for the brain
 *
 *	Description:	Creates a new Brain instance using a defined protein map as a base.
 *					Also adds a new spatial search instance, sets the brain's age to 0 and
 *					initializes all requisite brain plugins
**/
Brain::Brain (ProteinEnvironment *proteinMap){
    mProteinMap=proteinMap;
    mSpatialSearch=new SimpleSpatialSearch;
    mAge=0;
	mDevelopmentCounter=0;
	createInputRegion(INPUT_NEURONS);
    makeInitialNeurons();
    BrainPlugins::constructAll(this).swap(mPlugins);
}

void Brain::syncEnvironmentNeurons(unsigned int index, ProteinEnvironment::iterator environmentIterator){
    Elysia::Genome::Effect growEffect=Elysia::Genome::GROW_NEURON;
    float neuronDensity =environmentIterator.getProteinDensity(growEffect);
    BoundingBox3f3f bounds = environmentIterator.getBoundingBox();
    float area = bounds.across().x*bounds.across().y;
    float expectedNumNeurons=neuronDensity*area;
    boost::minstd_rand randGen(1+index);//needs to be >0
    boost::uniform_real<> uni_dist(0.0f,1.0f);
    boost::variate_generator<boost::minstd_rand, boost::uniform_real<> > uniform(randGen,uni_dist);
    if (expectedNumNeurons-floor(expectedNumNeurons)<uniform()) {
        expectedNumNeurons=ceil(expectedNumNeurons);
    }else {
        expectedNumNeurons=floor(expectedNumNeurons);
    }
    int numNeurons=(unsigned int)expectedNumNeurons;
    if (numNeurons<mNumNeurons[index]) {
        //FIXME: do we want to delete excess neurons
    }
    for (int n=mNumNeurons[index];n<numNeurons;++n) {
        this->addNeuron(bounds, environmentIterator.retrieveGene(growEffect));
    }
    if (mNumNeurons[index]!=numNeurons) {
        fprintf(stderr,"The index count isn't equal to the sync count:\nthis could happen if a neuron lies at the exact edge of a lobe,\nso don't panic, but verify that this is indeed the case\nand the wrong count got updated for that neuron");
    }
}

void Brain::makeInitialNeurons() {
    unsigned int index=0;
    for (ProteinEnvironment::iterator i=mProteinMap->begin();
         i!=mProteinMap->end();
         ++i,++index) {
        mNumNeurons[i.uid()]=0;
        syncEnvironmentNeurons(index,i);
        //FIXME add numNeurons to the count in this protein zone so we can add/remove more later
    }
}

Neuron * Brain::addNeuron(const BoundingBox3f3f&generationArea, const Genome::Gene&gene) {
    Vector3f v = generationArea.min();
    v.x+=generationArea.across().x*(rand()/(double)RAND_MAX);
    v.y+=generationArea.across().y*(rand()/(double)RAND_MAX);
	v.z=0;	 //Fixing z to 0 for now.
    //v.z+=generationArea.across().z*(rand()/(double)RAND_MAX);
	Neuron *n = new Neuron(this, 2, 3, 4, 1, 1, v, gene);
    mAllNeurons.insert(n);
    return n;
}

/**
 *	Description:	One "tick" of the brain simulation code, where the following occurs:
 *					 - processNeuron() called
 *					 - processSynapes() called
 *					 - increments the current time in the simulation
 *					 - ages the brain
 *					 - updates all the plugins for this brain
**/
void Brain::tick(){
	processNeuron();
	processSynapse();
	//developAllNeurons();
    ++mCurTime;
	++mDevelopmentCounter;
	if(mDevelopmentCounter%10 == 0)this->processDevelopment();
    mAge+=1.0e-6;//fixme this is probably not correct: we probably need genes to do this
    if (mAge>1.0) mAge=1.0;
    for(std::vector<BrainPlugin*>::iterator i=mPlugins.begin(),ie=mPlugins.end();i!=ie;++i) {
        (*i)->update();
    }
}

void Brain::developAllNeurons(){
	for(std::set<Neuron*>::iterator i=mAllNeurons.begin(),ie=mAllNeurons.end();i!=ie;++i){
		(*i)->developSynapse((*i)->getActivityStats());
	}
}

/**
 *	Description:	Updates all neurons in the neuron list for this brain, then clears the list of
 *					active neurons
**/
void Brain::processNeuron(){
	for (std::list<Neuron*>::iterator i=mActiveNeurons.begin(),ie=mActiveNeurons.end();
         i!=ie;
		 ++i) {
        (*i)->tick();
	}
	mActiveNeurons.clear();
}

/**
 *	Description:	Iterates through brain's associates synapses and updates all of them using
 *					the Synapse class residualFire() method
**/
void Brain::processSynapse(){
    std::list<Synapse*>::iterator j,i=mActiveSynapses.begin(),ie=mActiveSynapses.end();
	while (i!=ie) {
        std::list<Synapse*>::iterator j=i++;
        (*j)->residualFire();
	}
}

/**
 *	@param Synapse *inactiveSynapse - synapse to remove
 *
 *	Description:	Removes a synapse from the synapse list and updates it.
**/
void Brain::inactivateSynapse(Synapse *inactiveSynapse){
    if (inactiveSynapse->mWhere!=activeSynapseListSentinel()) {
        mActiveSynapses.erase(inactiveSynapse->mWhere);
        inactiveSynapse->mWhere=activeSynapseListSentinel();
    }
}

void Brain::deleteSynapse(Synapse *deletedSynapse){
	//mActiveSynapses.erase(deletedSynapse->mWhere);
}

/**
 *	@param Neuron *inactiveNeuron - an inactive neuron to remove
 *
 *	Description:	Removes an unused neuron from the neuron list and updates
**/
void Brain::inactivateNeuron(Neuron *inactiveNeuron){
    if (inactiveNeuron->mWhere!=activeNeuronListSentinel()) {
        mActiveNeurons.erase(inactiveNeuron->mWhere);
        inactiveNeuron->mWhere=activeNeuronListSentinel();
    }
}

void Brain::deleteNeuron(Neuron *deletedNeuron){
	//mAllNeurons.erase(deletedNeuron->mWhere);
}

/**
 *	@param Synapse *activeSynapse - a synapse to activate
 *	@return	the beginning element of the active synapses list for this brain
 *
 *	Description:	Adds a new synapse to the brain (at front of active synapse list)
 *					and returns the front element of the list
**/
std::list<Synapse *>::iterator Brain::activateSynapse(Synapse *activeSynapse){
    mActiveSynapses.push_front(activeSynapse);
    return mActiveSynapses.begin();
}
/**
 *	@param Neuron *activeNeuron - a neuron to activate
 *	@return	the beginning element of the active neuron list for this brain
 *
 *	Description:	Adds a new neuron to the brain (at front of active neuron list)
 *					and returns the front element of the list
**/
std::list<Neuron *>::iterator Brain::activateNeuron(Neuron *activeNeuron){
  activeNeuron->mActivity=5.0f;
  mActiveNeurons.push_front(activeNeuron);
  return mActiveNeurons.begin();
}

/**
 *	Brain destructor
**/
Brain::~Brain() {
	for(std::set<Neuron*>::iterator i=mAllNeurons.begin(),ie=mAllNeurons.end();i!=ie;++i){
		delete *i;
	}
    delete mSpatialSearch;
    delete mProteinMap;
    for (std::vector<BrainPlugin*>::iterator i=mPlugins.begin(),ie=mPlugins.end();i!=ie;++i) {
        delete *i;
    }
}

Neuron* Brain::createInputNeuron(float x, float y, float z, float spread){
	Genome::Gene gene;
    Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
    Genome::TemporalBoundingBox *dendritebb=gene.add_bounds();
    sourcebb->set_minx(x-spread);
    sourcebb->set_miny(y-spread);
    sourcebb->set_minz(0);
    sourcebb->set_maxx(x+spread);
    sourcebb->set_maxy(y+spread);
    sourcebb->set_maxz(0);

    dendritebb->set_minx(0);
    dendritebb->set_miny(0);
    dendritebb->set_minz(0);
    dendritebb->set_maxx(0);
    dendritebb->set_maxy(0);
    dendritebb->set_maxz(0);

	Vector3f v;
	v.x = x;
	v.y = y;
	v.z = z;
	Neuron *n;
	this->mAllNeurons.insert(n = new Neuron(this, 0, 0, 0, 1, 1, v,gene));
	this->mDevelopingNeurons.insert(n);
	return n;
}

void Brain::createInputRegion(int neurons){
	//At present, reserved location of input lobe is <0,0,0> to <5,5,0> neurons are added at 0.01 increments
	float minx = INPUT_REGION_MINX;
	float maxx = INPUT_REGION_MAXX;
	float miny = INPUT_REGION_MINY;
	float maxy = INPUT_REGION_MAXY;
	float spacing = INPUT_REGION_SPACING;
	float spread = INPUT_AXON_SPREAD;

	if(neurons > (maxx-minx)*(maxy-miny)/spacing){
		assert(this);
	}
	Neuron* n;
	float x=minx;
	float y=miny;

	for(int i=0;i<neurons;i++){
		n = createInputNeuron(x,y,0,spread);
		mInputNeurons.push_back(n);
		x += spacing;
		if(x >= maxx){
			x = minx;
			y += spacing;
		}
	}
}

void Brain::fireInputNeuron(int neuronNumber){
	Neuron* n= mInputNeurons[neuronNumber];
	n->setActivity(5);
	this -> activateNeuron(n);
	//printf("input");
}

void Brain::processDevelopment(){
	for(std::set<Neuron*>::iterator i=mAllNeurons.begin(),ie=mAllNeurons.end();i!=ie;++i){
		(*i)->tick();
	}
}

/**
 * @return the bounds of all genes in the brain, i.e. where the farthest neurons may spout
 */
BoundingBox3f3f Brain::getBounds()const{

//    return BoundingBox3f3f(Vector3f(0,00,00),Vector3f(1000,1000,1000));
    return mProteinMap->getBounds();
}

}

<|endoftext|>


<commit_before>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <ctype.h>                                          /* isxxx() */
#include <ros/ros.h>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */
#include <base_controller/md49data.h>                       /* Custom message /encoders */
#include <sqlite3.h>

int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                     /* speed to set for MD49 */
unsigned char last_speed_l=128, last_speed_r=128;           /* speed to set for MD49 */
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

unsigned char serialBuffer[18];                             /* Serial buffer to store uart data */
void read_MD49_Data (void);
void set_md49_speed (unsigned char speed_l, unsigned char speed_r);

// sqlite globals
sqlite3 *db;
char *zErrMsg = 0;
int  rc;
const char *sql;
const char* data = "Callback function called";

using namespace std;

base_controller::encoders encoders;
base_controller::md49data md49data;

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

        if (vel_cmd.linear.x>0){
            speed_l = 200;
            speed_r = 200;
        }
        if (vel_cmd.linear.x<0){
            speed_l = 100;
            speed_r = 100;
        }
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
            speed_l = 128;
            speed_r = 128;
        }
        if (vel_cmd.angular.z>0){
            speed_l = 100;
            speed_r = 200;
        }
        if (vel_cmd.angular.z<0){
            speed_l = 200;
            speed_r = 100;
        }

    /*
        //ANFANG Alternative
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
        else if(vel_cmd.linear.x == 0){
            // turning
            vr = vel_cmd.angular.z * base_width / 2.0;
            vl = (-1) * vr;
        }
        else if(vel_cmd.angular.z == 0){
            // forward / backward
            vl = vr = vel_cmd.linear.x;
        }
        else{
            // moving doing arcs
            vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
            if (vl > max_vl) {vl=max_vl;}
            if (vl < min_vl) {vl=min_vl;}
            vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
            if (vr > max_vr) {vr=max_vr;}
            if (vr < min_vr) {vr=min_vr;}
        }
        //ENDE Alternative
    */
}

int main( int argc, char* argv[] ){

    // Setup as ROS node
    // *****************
    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 10, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",10);
    ros::Publisher md49data_pub = n.advertise<base_controller::md49data>("md49data",10);

    ros::Rate loop_rate(10);
    ROS_INFO("Starting base_controller node:");
    ROS_INFO("============================================");
    ROS_INFO("subscribing to /cmd_vel");
    ROS_INFO("publishing to /encoders");
    ROS_INFO("publishing to /md49data");
    ROS_INFO("============================================");

    // Open database md49data.db and add
    // table md49commands
    // *********************************
    rc = sqlite3_open("data/md49data.db", &db);
    if( rc ){
        ROS_INFO("Can't open database: %s", sqlite3_errmsg(db));
        exit(0);
    }else{
        ROS_INFO("Opened database successfully,");
    }

    // Create table md49commands
    // *************************
    sql = "CREATE TABLE md49commands("  \
     "ID INT PRIMARY KEY     NOT NULL," \
     "SpeedL         INT DEFAULT 128," \
     "SpeedR         INT DEFAULT 128 );" \
     "INSERT INTO md49commands (ID,SpeedL,SpeedR) VALUES (1,128,128);";
    rc = sqlite3_exec(db, sql, NULL, 0, &zErrMsg);                      // Execute SQL statement
    if( rc != SQLITE_OK ){
        ROS_INFO("SQL message: %s", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        ROS_INFO("table created successfully");
    }

    // Set SpeedL and SpeedR to
    // defaults =128
    // ************************
    char sql_buffer[200];
    int cx;
    cx = snprintf (sql_buffer,200,"UPDATE md49commands SET SpeedL=%i, SpeedR=%i WHERE ID=1", 128,128);

    rc = sqlite3_exec(db, sql_buffer, NULL, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        ROS_INFO("SQL message: %s", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        ROS_INFO("SpeedL & SpeedR set to defaults in Table md49commands(md49data.db)");
    }

    while(n.ok())
    {
        // Read encoder values and other data from MD49:
        // serial_controller_node reads data from AVR-Master
        // and provides that data in md49_data.txt
        // *************************************************
//        read_MD49_Data();

        // Set MD49 speed_l and speed_r:
        // serial_controller_node reads commands from
        // md49_commands.txt and writes commands to AVR-Master
        // ***************************************************
        if ((speed_l != last_speed_l) || (speed_r != last_speed_r)){
            set_md49_speed(speed_l,speed_r);
            last_speed_l=speed_l;
            last_speed_r=speed_r;
        }

        // Publish encoder values to topic /encoders (custom message)
        // **********************************************************
        encoders.encoder_l=EncoderL;
        encoders.encoder_r=EncoderR;
        encoders_pub.publish(encoders);

        // Publish MD49 data to topic /md49data (custom message)
        // *****************************************************
        md49data.speed_l = serialBuffer[8];
        md49data.speed_r = serialBuffer[9];
        md49data.volt = serialBuffer[10];
        md49data.current_l = serialBuffer[11];
        md49data.current_r = serialBuffer[12];
        md49data.error = serialBuffer[13];
        md49data.acceleration = serialBuffer[14];
        md49data.mode = serialBuffer[15];
        md49data.regulator = serialBuffer[16];
        md49data.timeout = serialBuffer[17];
        md49data_pub.publish(md49data);

        ros::spinOnce();
        loop_rate.sleep();

    }// end.mainloop

    return 1;
} // end.main

void read_MD49_Data (void){

    // Read all MD49 data from md49_data.txt
    // *************************************
    string line;
    ifstream myfile ("md49_data.txt");
    if (myfile.is_open()){
        int i=0;
        while (getline (myfile,line)){
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            serialBuffer[i]=atoi(data);
            i =i++;
        }
        myfile.close();

    }
    else ROS_ERROR("Unable to open file: md49_data.txt");

    // Put toghether new encodervalues
    // *******************************
    EncoderL = serialBuffer[0] << 24;                        // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                        // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

}

void set_md49_speed (unsigned char speed_l, unsigned char speed_r){

    // Set SpeedL=speed_l and
    // SpeedR=speed_r in Table md49commands
    // ************************************
    char sql_buffer[200];
    int cx;
    cx = snprintf (sql_buffer,200,"UPDATE md49commands SET SpeedL=%i, SpeedR=%i WHERE ID=1", speed_l,speed_r);

    rc = sqlite3_exec(db, sql_buffer, NULL, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        ROS_WARN("SQL message: %s", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        ROS_INFO("Set SpeedL=%i and SpeedR=%i in Table md49commands(md49data.db)",speed_l, speed_r);
    }
}

<commit_msg>Update code<commit_after>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <ctype.h>                                          /* isxxx() */
#include <ros/ros.h>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */
#include <base_controller/md49data.h>                       /* Custom message /encoders */
#include <sqlite3.h>

int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                     /* speed to set for MD49 */
unsigned char last_speed_l=128, last_speed_r=128;           /* speed to set for MD49 */
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

unsigned char serialBuffer[18];                             /* Serial buffer to store uart data */
void read_MD49_Data (void);
void set_md49_speed (unsigned char speed_l, unsigned char speed_r);

// sqlite globals
sqlite3 *db;
char *zErrMsg = 0;
int  rc;
const char *sql;
const char* data = "Callback function called";

using namespace std;

base_controller::encoders encoders;
base_controller::md49data md49data;

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

        if (vel_cmd.linear.x>0){
            speed_l = 255;
            speed_r = 255;
        }
        if (vel_cmd.linear.x<0){
            speed_l = 1;
            speed_r = 1;
        }
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
            speed_l = 128;
            speed_r = 128;
        }
        if (vel_cmd.angular.z>0){
            speed_l = 1;
            speed_r = 255;
        }
        if (vel_cmd.angular.z<0){
            speed_l = 255;
            speed_r = 1;
        }

    /*
        //ANFANG Alternative
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
        else if(vel_cmd.linear.x == 0){
            // turning
            vr = vel_cmd.angular.z * base_width / 2.0;
            vl = (-1) * vr;
        }
        else if(vel_cmd.angular.z == 0){
            // forward / backward
            vl = vr = vel_cmd.linear.x;
        }
        else{
            // moving doing arcs
            vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
            if (vl > max_vl) {vl=max_vl;}
            if (vl < min_vl) {vl=min_vl;}
            vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
            if (vr > max_vr) {vr=max_vr;}
            if (vr < min_vr) {vr=min_vr;}
        }
        //ENDE Alternative
    */
}

int main( int argc, char* argv[] ){

    // Setup as ROS node
    // *****************
    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 10, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",10);
    ros::Publisher md49data_pub = n.advertise<base_controller::md49data>("md49data",10);

    ros::Rate loop_rate(10);
    ROS_INFO("Starting base_controller node:");
    ROS_INFO("============================================");
    ROS_INFO("subscribing to /cmd_vel");
    ROS_INFO("publishing to /encoders");
    ROS_INFO("publishing to /md49data");
    ROS_INFO("============================================");

    // Open database md49data.db and add
    // table md49commands
    // *********************************
    rc = sqlite3_open("data/md49data.db", &db);
    if( rc ){
        ROS_INFO("Can't open database: %s", sqlite3_errmsg(db));
        exit(0);
    }else{
        ROS_INFO("Opened database successfully,");
    }

    // Create table md49commands
    // *************************
    sql = "CREATE TABLE md49commands("  \
     "ID INT PRIMARY KEY     NOT NULL," \
     "SpeedL         INT DEFAULT 128," \
     "SpeedR         INT DEFAULT 128 );" \
     "INSERT INTO md49commands (ID,SpeedL,SpeedR) VALUES (1,128,128);";
    rc = sqlite3_exec(db, sql, NULL, 0, &zErrMsg);                      // Execute SQL statement
    if( rc != SQLITE_OK ){
        ROS_INFO("SQL message: %s", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        ROS_INFO("table created successfully");
    }

    // Set SpeedL and SpeedR to
    // defaults =128
    // ************************
    char sql_buffer[200];
    int cx;
    cx = snprintf (sql_buffer,200,"UPDATE md49commands SET SpeedL=%i, SpeedR=%i WHERE ID=1", 128,128);

    rc = sqlite3_exec(db, sql_buffer, NULL, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        ROS_INFO("SQL message: %s", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        ROS_INFO("SpeedL & SpeedR set to defaults in Table md49commands(md49data.db)");
    }

    while(n.ok())
    {
        // Read encoder values and other data from MD49:
        // serial_controller_node reads data from AVR-Master
        // and provides that data in md49_data.txt
        // *************************************************
//        read_MD49_Data();

        // Set MD49 speed_l and speed_r:
        // serial_controller_node reads commands from
        // md49_commands.txt and writes commands to AVR-Master
        // ***************************************************
        if ((speed_l != last_speed_l) || (speed_r != last_speed_r)){
            set_md49_speed(speed_l,speed_r);
            last_speed_l=speed_l;
            last_speed_r=speed_r;
        }

        // Publish encoder values to topic /encoders (custom message)
        // **********************************************************
        encoders.encoder_l=EncoderL;
        encoders.encoder_r=EncoderR;
        encoders_pub.publish(encoders);

        // Publish MD49 data to topic /md49data (custom message)
        // *****************************************************
        md49data.speed_l = serialBuffer[8];
        md49data.speed_r = serialBuffer[9];
        md49data.volt = serialBuffer[10];
        md49data.current_l = serialBuffer[11];
        md49data.current_r = serialBuffer[12];
        md49data.error = serialBuffer[13];
        md49data.acceleration = serialBuffer[14];
        md49data.mode = serialBuffer[15];
        md49data.regulator = serialBuffer[16];
        md49data.timeout = serialBuffer[17];
        md49data_pub.publish(md49data);

        ros::spinOnce();
        loop_rate.sleep();

    }// end.mainloop

    return 1;
} // end.main

void read_MD49_Data (void){

    // Read all MD49 data from md49_data.txt
    // *************************************
    string line;
    ifstream myfile ("md49_data.txt");
    if (myfile.is_open()){
        int i=0;
        while (getline (myfile,line)){
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            serialBuffer[i]=atoi(data);
            i =i++;
        }
        myfile.close();

    }
    else ROS_ERROR("Unable to open file: md49_data.txt");

    // Put toghether new encodervalues
    // *******************************
    EncoderL = serialBuffer[0] << 24;                        // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                        // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

}

void set_md49_speed (unsigned char speed_l, unsigned char speed_r){

    // Set SpeedL=speed_l and
    // SpeedR=speed_r in Table md49commands
    // ************************************
    char sql_buffer[200];
    int cx;
    cx = snprintf (sql_buffer,200,"UPDATE md49commands SET SpeedL=%i, SpeedR=%i WHERE ID=1", speed_l,speed_r);

    rc = sqlite3_exec(db, sql_buffer, NULL, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        ROS_WARN("SQL message: %s", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        ROS_INFO("Set SpeedL=%i and SpeedR=%i in Table md49commands(md49data.db)",speed_l, speed_r);
    }
}

<|endoftext|>


<commit_before>//===--- CompletionInstance.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/CompletionInstance.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/Module.h"
#include "swift/AST/SourceFile.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Driver/FrontendUtil.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace swift;
using namespace ide;

std::unique_ptr<llvm::MemoryBuffer>
swift::ide::makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
                                           unsigned &Offset,
                                           StringRef bufferIdentifier) {

  auto origBuffSize = origBuf->getBufferSize();
  if (Offset > origBuffSize)
    Offset = origBuffSize;

  auto newBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
      origBuffSize + 1, bufferIdentifier);
  auto *pos = origBuf->getBufferStart() + Offset;
  auto *newPos =
      std::copy(origBuf->getBufferStart(), pos, newBuffer->getBufferStart());
  *newPos = '\0';
  std::copy(pos, origBuf->getBufferEnd(), newPos + 1);

  return std::unique_ptr<llvm::MemoryBuffer>(newBuffer.release());
}

namespace {
/// Returns index number of \p D in \p Decls . If it's not found, returns ~0.
template <typename Range>
unsigned findIndexInRange(Decl *D, const Range &Decls) {
  unsigned N = 0;
  for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
    if ((*I)->isImplicit())
      continue;
    if (*I == D)
      return N;
    ++N;
  }
  return ~0U;
}

/// Return the element at \p N in \p Decls .
template <typename Range> Decl *getElementAt(const Range &Decls, unsigned N) {
  for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
    if ((*I)->isImplicit())
      continue;
    if (N == 0)
      return *I;
    --N;
  }
  return nullptr;
}

/// Find the equivalent \c DeclContext with \p DC from \p SF AST.
/// This assumes the AST which contains \p DC has exact the same structure with
/// \p SF.
/// FIXME: This doesn't support IfConfigDecl blocks. If \p DC is in an inactive
///        config block, this function returns \c false.
static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
                                                           SourceFile *SF) {
  auto *newDC = DC;
  // NOTE: Shortcut for DC->getParentSourceFile() == SF case is not needed
  // because they should be always different.

  // Get the index path in the current AST.
  SmallVector<unsigned, 4> IndexStack;
  do {
    auto *D = newDC->getAsDecl();
    if (!D)
      return nullptr;
    auto *parentDC = newDC->getParent();
    unsigned N;

    if (auto accessor = dyn_cast<AccessorDecl>(D)) {
      // The AST for accessors is like:
      //   DeclContext -> AbstractStorageDecl -> AccessorDecl
      // We need to push the index of the accessor within the accessor list
      // of the storage.
      auto *storage = accessor->getStorage();
      if (!storage)
        return nullptr;
      auto accessorN = findIndexInRange(accessor, storage->getAllAccessors());
      IndexStack.push_back(accessorN);
      D = storage;
    }

    if (auto parentSF = dyn_cast<SourceFile>(parentDC))
      N = findIndexInRange(D, parentSF->getTopLevelDecls());
    else if (auto parentIDC =
                 dyn_cast<IterableDeclContext>(parentDC->getAsDecl()))
      N = findIndexInRange(D, parentIDC->getMembers());
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (indexpath)");

    // Not found in the decl context tree.
    // FIXME: Probably DC is in an inactive #if block.
    if (N == ~0U) {
      return nullptr;
    }

    IndexStack.push_back(N);
    newDC = parentDC;
  } while (!newDC->isModuleScopeContext());

  assert(isa<SourceFile>(newDC) && "DC should be in a SourceFile");

  // Query the equivalent decl context from the base SourceFile using the index
  // path.
  newDC = SF;
  do {
    auto N = IndexStack.pop_back_val();
    Decl *D;
    if (auto parentSF = dyn_cast<SourceFile>(newDC))
      D = getElementAt(parentSF->getTopLevelDecls(), N);
    else if (auto parentIDC = dyn_cast<IterableDeclContext>(newDC->getAsDecl()))
      D = getElementAt(parentIDC->getMembers(), N);
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (query)");

    if (auto storage = dyn_cast<AbstractStorageDecl>(D)) {
      if (IndexStack.empty())
        return nullptr;
      auto accessorN = IndexStack.pop_back_val();
      D = getElementAt(storage->getAllAccessors(), accessorN);
    }

    newDC = dyn_cast<DeclContext>(D);
    if (!newDC)
      return nullptr;
  } while (!IndexStack.empty());

  assert(newDC->getContextKind() == DC->getContextKind());

  return newDC;
}

} // namespace

bool CompletionInstance::performCachedOperaitonIfPossible(
    const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  if (!CachedCI)
    return false;
  if (CachedReuseCount >= MaxASTReuseCount)
    return false;
  if (CachedArgHash != ArgsHash)
    return false;

  auto &CI = *CachedCI;

  if (!CI.hasPersistentParserState())
    return false;
  auto &oldState = CI.getPersistentParserState();
  if (!oldState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &SM = CI.getSourceMgr();
  if (SM.getIdentifierForBuffer(SM.getCodeCompletionBufferID()) !=
      completionBuffer->getBufferIdentifier())
    return false;

  auto &oldInfo = oldState.getCodeCompletionDelayedDeclState();

  // Currently, only completions within a function body is supported.
  if (oldInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  // Parse the new buffer into temporary SourceFile.
  SourceManager tmpSM;
  auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
  tmpSM.setCodeCompletionPoint(tmpBufferID, Offset);

  LangOptions langOpts;
  langOpts.DisableParserLookup = true;
  TypeCheckerOptions typeckOpts;
  SearchPathOptions searchPathOpts;
  DiagnosticEngine tmpDiags(tmpSM);
  std::unique_ptr<ASTContext> Ctx(
      ASTContext::get(langOpts, typeckOpts, searchPathOpts, tmpSM, tmpDiags));
  registerIDERequestFunctions(Ctx->evaluator);
  registerTypeCheckerRequestFunctions(Ctx->evaluator);
  registerSILGenRequestFunctions(Ctx->evaluator);
  ModuleDecl *M = ModuleDecl::create(Identifier(), *Ctx);
  PersistentParserState newState;
  SourceFile *newSF =
      new (*Ctx) SourceFile(*M, SourceFileKind::Library, tmpBufferID,
                            SourceFile::ImplicitModuleImportKind::None);
  newSF->enableInterfaceHash();
  // Ensure all non-function-body tokens are hashed into the interface hash
  Ctx->LangOpts.EnableTypeFingerprints = false;
  parseIntoSourceFileFull(*newSF, tmpBufferID, &newState);
  // Couldn't find any completion token?
  if (!newState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &newInfo = newState.getCodeCompletionDelayedDeclState();

  // The new completion must happens in function body too.
  if (newInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  auto *oldSF = oldInfo.ParentContext->getParentSourceFile();

  // If the interface has changed, AST must be refreshed.
  llvm::SmallString<32> oldInterfaceHash{};
  llvm::SmallString<32> newInterfaceHash{};
  oldSF->getInterfaceHash(oldInterfaceHash);
  newSF->getInterfaceHash(newInterfaceHash);
  if (oldInterfaceHash != newInterfaceHash)
    return false;

  DeclContext *DC =
      getEquivalentDeclContextFromSourceFile(newInfo.ParentContext, oldSF);
  if (!DC)
    return false;

  // OK, we can perform fast completion for this. Update the orignal delayed
  // decl state.

  // Fast completion keeps the buffer in memory for multiple completions.
  // To reduce the consumption, slice the source buffer so it only holds
  // the portion that is needed for the second pass.
  auto startOffset = newInfo.StartOffset;
  if (newInfo.PrevOffset != ~0u)
    startOffset = newInfo.PrevOffset;
  auto startLoc = tmpSM.getLocForOffset(tmpBufferID, startOffset);
  startLoc = Lexer::getLocForStartOfLine(tmpSM, startLoc);
  startOffset = tmpSM.getLocOffsetInBuffer(startLoc, tmpBufferID);

  auto endOffset = newInfo.EndOffset;
  auto endLoc = tmpSM.getLocForOffset(tmpBufferID, endOffset);
  endLoc = Lexer::getLocForEndOfToken(tmpSM, endLoc);
  endOffset = tmpSM.getLocOffsetInBuffer(endLoc, tmpBufferID);

  newInfo.StartOffset -= startOffset;
  newInfo.EndOffset -= startOffset;
  if (newInfo.PrevOffset != ~0u)
    newInfo.PrevOffset -= startOffset;

  auto sourceText = completionBuffer->getBuffer().slice(startOffset, endOffset);
  auto newOffset = Offset - startOffset;

  auto newBufferID =
      SM.addMemBufferCopy(sourceText, completionBuffer->getBufferIdentifier());
  SM.openVirtualFile(SM.getLocForBufferStart(newBufferID),
                     tmpSM.getDisplayNameForLoc(startLoc),
                     tmpSM.getLineAndColumn(startLoc).first - 1);
  SM.setCodeCompletionPoint(newBufferID, newOffset);

  // Construct dummy scopes. We don't need to restore the original scope
  // because they are probably not 'isResolvable()' anyway.
  auto &SI = oldState.getScopeInfo();
  assert(SI.getCurrentScope() == nullptr);
  Scope Top(SI, ScopeKind::TopLevel);
  Scope Body(SI, ScopeKind::FunctionBody);

  oldInfo.ParentContext = DC;
  oldInfo.StartOffset = newInfo.StartOffset;
  oldInfo.EndOffset = newInfo.EndOffset;
  oldInfo.PrevOffset = newInfo.PrevOffset;
  oldState.restoreCodeCompletionDelayedDeclState(oldInfo);

  auto *AFD = cast<AbstractFunctionDecl>(DC);
  if (AFD->isBodySkipped())
    AFD->setBodyDelayed(AFD->getBodySourceRange());
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  CI.getDiags().diagnose(SM.getLocForOffset(newBufferID, newInfo.StartOffset),
                         diag::completion_reusing_astcontext);

  Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  CachedReuseCount += 1;

  return true;
}

bool CompletionInstance::performNewOperation(
    Optional<llvm::hash_code> ArgsHash, swift::CompilerInvocation &Invocation,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  auto TheInstance = std::make_unique<CompilerInstance>();
  auto &CI = *TheInstance;
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  if (FileSystem != llvm::vfs::getRealFileSystem())
    CI.getSourceMgr().setFileSystem(FileSystem);

  Invocation.setCodeCompletionPoint(completionBuffer, Offset);

  if (CI.setup(Invocation)) {
    Error = "failed to setup compiler instance";
    return false;
  }
  registerIDERequestFunctions(CI.getASTContext().evaluator);

  CI.performParseAndResolveImportsOnly();
  if (CI.hasPersistentParserState())
    Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  if (ArgsHash.hasValue()) {
    CachedCI = std::move(TheInstance);
    CachedArgHash = *ArgsHash;
    CachedReuseCount = 0;
  }

  return true;
}

bool swift::ide::CompletionInstance::performOperation(
    swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    bool EnableASTCaching, std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  // Always disable source location resolutions from .swiftsourceinfo file
  // because they're somewhat heavy operations and aren't needed for completion.
  Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;

  // Disable to build syntax tree because code-completion skips some portion of
  // source text. That breaks an invariant of syntax tree building.
  Invocation.getLangOptions().BuildSyntaxTree = false;

  // This validation may call stat(2) many times. Disable it to prevent
  // performance regression.
  Invocation.getSearchPathOptions().DisableModulesValidateSystemDependencies =
      true;

  // Since caching uses the interface hash, and since per type fingerprints
  // weaken that hash, disable them here:
  Invocation.getLangOptions().EnableTypeFingerprints = false;

  // FIXME: ASTScopeLookup doesn't support code completion yet.
  Invocation.disableASTScopeLookup();

  if (EnableASTCaching) {
    // Compute the signature of the invocation.
    llvm::hash_code ArgsHash(0);
    for (auto arg : Args)
      ArgsHash = llvm::hash_combine(ArgsHash, StringRef(arg));

    // Concurrent completions will block so that they have higher chance to use
    // the cached completion instance.
    std::lock_guard<std::mutex> lock(mtx);

    if (performCachedOperaitonIfPossible(Invocation, ArgsHash, completionBuffer,
                                         Offset, DiagC, Callback))
      return true;

    if (performNewOperation(ArgsHash, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  } else {
    // Concurrent completions may happen in parallel when caching is disabled.
    if (performNewOperation(None, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  }

  assert(!Error.empty());
  return false;
}
<commit_msg>Revert "[CodeCompletion] Disable module system headers validation"<commit_after>//===--- CompletionInstance.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/CompletionInstance.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/Module.h"
#include "swift/AST/SourceFile.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Driver/FrontendUtil.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace swift;
using namespace ide;

std::unique_ptr<llvm::MemoryBuffer>
swift::ide::makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
                                           unsigned &Offset,
                                           StringRef bufferIdentifier) {

  auto origBuffSize = origBuf->getBufferSize();
  if (Offset > origBuffSize)
    Offset = origBuffSize;

  auto newBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
      origBuffSize + 1, bufferIdentifier);
  auto *pos = origBuf->getBufferStart() + Offset;
  auto *newPos =
      std::copy(origBuf->getBufferStart(), pos, newBuffer->getBufferStart());
  *newPos = '\0';
  std::copy(pos, origBuf->getBufferEnd(), newPos + 1);

  return std::unique_ptr<llvm::MemoryBuffer>(newBuffer.release());
}

namespace {
/// Returns index number of \p D in \p Decls . If it's not found, returns ~0.
template <typename Range>
unsigned findIndexInRange(Decl *D, const Range &Decls) {
  unsigned N = 0;
  for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
    if ((*I)->isImplicit())
      continue;
    if (*I == D)
      return N;
    ++N;
  }
  return ~0U;
}

/// Return the element at \p N in \p Decls .
template <typename Range> Decl *getElementAt(const Range &Decls, unsigned N) {
  for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
    if ((*I)->isImplicit())
      continue;
    if (N == 0)
      return *I;
    --N;
  }
  return nullptr;
}

/// Find the equivalent \c DeclContext with \p DC from \p SF AST.
/// This assumes the AST which contains \p DC has exact the same structure with
/// \p SF.
/// FIXME: This doesn't support IfConfigDecl blocks. If \p DC is in an inactive
///        config block, this function returns \c false.
static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
                                                           SourceFile *SF) {
  auto *newDC = DC;
  // NOTE: Shortcut for DC->getParentSourceFile() == SF case is not needed
  // because they should be always different.

  // Get the index path in the current AST.
  SmallVector<unsigned, 4> IndexStack;
  do {
    auto *D = newDC->getAsDecl();
    if (!D)
      return nullptr;
    auto *parentDC = newDC->getParent();
    unsigned N;

    if (auto accessor = dyn_cast<AccessorDecl>(D)) {
      // The AST for accessors is like:
      //   DeclContext -> AbstractStorageDecl -> AccessorDecl
      // We need to push the index of the accessor within the accessor list
      // of the storage.
      auto *storage = accessor->getStorage();
      if (!storage)
        return nullptr;
      auto accessorN = findIndexInRange(accessor, storage->getAllAccessors());
      IndexStack.push_back(accessorN);
      D = storage;
    }

    if (auto parentSF = dyn_cast<SourceFile>(parentDC))
      N = findIndexInRange(D, parentSF->getTopLevelDecls());
    else if (auto parentIDC =
                 dyn_cast<IterableDeclContext>(parentDC->getAsDecl()))
      N = findIndexInRange(D, parentIDC->getMembers());
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (indexpath)");

    // Not found in the decl context tree.
    // FIXME: Probably DC is in an inactive #if block.
    if (N == ~0U) {
      return nullptr;
    }

    IndexStack.push_back(N);
    newDC = parentDC;
  } while (!newDC->isModuleScopeContext());

  assert(isa<SourceFile>(newDC) && "DC should be in a SourceFile");

  // Query the equivalent decl context from the base SourceFile using the index
  // path.
  newDC = SF;
  do {
    auto N = IndexStack.pop_back_val();
    Decl *D;
    if (auto parentSF = dyn_cast<SourceFile>(newDC))
      D = getElementAt(parentSF->getTopLevelDecls(), N);
    else if (auto parentIDC = dyn_cast<IterableDeclContext>(newDC->getAsDecl()))
      D = getElementAt(parentIDC->getMembers(), N);
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (query)");

    if (auto storage = dyn_cast<AbstractStorageDecl>(D)) {
      if (IndexStack.empty())
        return nullptr;
      auto accessorN = IndexStack.pop_back_val();
      D = getElementAt(storage->getAllAccessors(), accessorN);
    }

    newDC = dyn_cast<DeclContext>(D);
    if (!newDC)
      return nullptr;
  } while (!IndexStack.empty());

  assert(newDC->getContextKind() == DC->getContextKind());

  return newDC;
}

} // namespace

bool CompletionInstance::performCachedOperaitonIfPossible(
    const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  if (!CachedCI)
    return false;
  if (CachedReuseCount >= MaxASTReuseCount)
    return false;
  if (CachedArgHash != ArgsHash)
    return false;

  auto &CI = *CachedCI;

  if (!CI.hasPersistentParserState())
    return false;
  auto &oldState = CI.getPersistentParserState();
  if (!oldState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &SM = CI.getSourceMgr();
  if (SM.getIdentifierForBuffer(SM.getCodeCompletionBufferID()) !=
      completionBuffer->getBufferIdentifier())
    return false;

  auto &oldInfo = oldState.getCodeCompletionDelayedDeclState();

  // Currently, only completions within a function body is supported.
  if (oldInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  // Parse the new buffer into temporary SourceFile.
  SourceManager tmpSM;
  auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
  tmpSM.setCodeCompletionPoint(tmpBufferID, Offset);

  LangOptions langOpts;
  langOpts.DisableParserLookup = true;
  TypeCheckerOptions typeckOpts;
  SearchPathOptions searchPathOpts;
  DiagnosticEngine tmpDiags(tmpSM);
  std::unique_ptr<ASTContext> Ctx(
      ASTContext::get(langOpts, typeckOpts, searchPathOpts, tmpSM, tmpDiags));
  registerIDERequestFunctions(Ctx->evaluator);
  registerTypeCheckerRequestFunctions(Ctx->evaluator);
  registerSILGenRequestFunctions(Ctx->evaluator);
  ModuleDecl *M = ModuleDecl::create(Identifier(), *Ctx);
  PersistentParserState newState;
  SourceFile *newSF =
      new (*Ctx) SourceFile(*M, SourceFileKind::Library, tmpBufferID,
                            SourceFile::ImplicitModuleImportKind::None);
  newSF->enableInterfaceHash();
  // Ensure all non-function-body tokens are hashed into the interface hash
  Ctx->LangOpts.EnableTypeFingerprints = false;
  parseIntoSourceFileFull(*newSF, tmpBufferID, &newState);
  // Couldn't find any completion token?
  if (!newState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &newInfo = newState.getCodeCompletionDelayedDeclState();

  // The new completion must happens in function body too.
  if (newInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  auto *oldSF = oldInfo.ParentContext->getParentSourceFile();

  // If the interface has changed, AST must be refreshed.
  llvm::SmallString<32> oldInterfaceHash{};
  llvm::SmallString<32> newInterfaceHash{};
  oldSF->getInterfaceHash(oldInterfaceHash);
  newSF->getInterfaceHash(newInterfaceHash);
  if (oldInterfaceHash != newInterfaceHash)
    return false;

  DeclContext *DC =
      getEquivalentDeclContextFromSourceFile(newInfo.ParentContext, oldSF);
  if (!DC)
    return false;

  // OK, we can perform fast completion for this. Update the orignal delayed
  // decl state.

  // Fast completion keeps the buffer in memory for multiple completions.
  // To reduce the consumption, slice the source buffer so it only holds
  // the portion that is needed for the second pass.
  auto startOffset = newInfo.StartOffset;
  if (newInfo.PrevOffset != ~0u)
    startOffset = newInfo.PrevOffset;
  auto startLoc = tmpSM.getLocForOffset(tmpBufferID, startOffset);
  startLoc = Lexer::getLocForStartOfLine(tmpSM, startLoc);
  startOffset = tmpSM.getLocOffsetInBuffer(startLoc, tmpBufferID);

  auto endOffset = newInfo.EndOffset;
  auto endLoc = tmpSM.getLocForOffset(tmpBufferID, endOffset);
  endLoc = Lexer::getLocForEndOfToken(tmpSM, endLoc);
  endOffset = tmpSM.getLocOffsetInBuffer(endLoc, tmpBufferID);

  newInfo.StartOffset -= startOffset;
  newInfo.EndOffset -= startOffset;
  if (newInfo.PrevOffset != ~0u)
    newInfo.PrevOffset -= startOffset;

  auto sourceText = completionBuffer->getBuffer().slice(startOffset, endOffset);
  auto newOffset = Offset - startOffset;

  auto newBufferID =
      SM.addMemBufferCopy(sourceText, completionBuffer->getBufferIdentifier());
  SM.openVirtualFile(SM.getLocForBufferStart(newBufferID),
                     tmpSM.getDisplayNameForLoc(startLoc),
                     tmpSM.getLineAndColumn(startLoc).first - 1);
  SM.setCodeCompletionPoint(newBufferID, newOffset);

  // Construct dummy scopes. We don't need to restore the original scope
  // because they are probably not 'isResolvable()' anyway.
  auto &SI = oldState.getScopeInfo();
  assert(SI.getCurrentScope() == nullptr);
  Scope Top(SI, ScopeKind::TopLevel);
  Scope Body(SI, ScopeKind::FunctionBody);

  oldInfo.ParentContext = DC;
  oldInfo.StartOffset = newInfo.StartOffset;
  oldInfo.EndOffset = newInfo.EndOffset;
  oldInfo.PrevOffset = newInfo.PrevOffset;
  oldState.restoreCodeCompletionDelayedDeclState(oldInfo);

  auto *AFD = cast<AbstractFunctionDecl>(DC);
  if (AFD->isBodySkipped())
    AFD->setBodyDelayed(AFD->getBodySourceRange());
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  CI.getDiags().diagnose(SM.getLocForOffset(newBufferID, newInfo.StartOffset),
                         diag::completion_reusing_astcontext);

  Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  CachedReuseCount += 1;

  return true;
}

bool CompletionInstance::performNewOperation(
    Optional<llvm::hash_code> ArgsHash, swift::CompilerInvocation &Invocation,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  auto TheInstance = std::make_unique<CompilerInstance>();
  auto &CI = *TheInstance;
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  if (FileSystem != llvm::vfs::getRealFileSystem())
    CI.getSourceMgr().setFileSystem(FileSystem);

  Invocation.setCodeCompletionPoint(completionBuffer, Offset);

  if (CI.setup(Invocation)) {
    Error = "failed to setup compiler instance";
    return false;
  }
  registerIDERequestFunctions(CI.getASTContext().evaluator);

  CI.performParseAndResolveImportsOnly();
  if (CI.hasPersistentParserState())
    Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  if (ArgsHash.hasValue()) {
    CachedCI = std::move(TheInstance);
    CachedArgHash = *ArgsHash;
    CachedReuseCount = 0;
  }

  return true;
}

bool swift::ide::CompletionInstance::performOperation(
    swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    bool EnableASTCaching, std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  // Always disable source location resolutions from .swiftsourceinfo file
  // because they're somewhat heavy operations and aren't needed for completion.
  Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;

  // Disable to build syntax tree because code-completion skips some portion of
  // source text. That breaks an invariant of syntax tree building.
  Invocation.getLangOptions().BuildSyntaxTree = false;

  // Since caching uses the interface hash, and since per type fingerprints
  // weaken that hash, disable them here:
  Invocation.getLangOptions().EnableTypeFingerprints = false;

  // FIXME: ASTScopeLookup doesn't support code completion yet.
  Invocation.disableASTScopeLookup();

  if (EnableASTCaching) {
    // Compute the signature of the invocation.
    llvm::hash_code ArgsHash(0);
    for (auto arg : Args)
      ArgsHash = llvm::hash_combine(ArgsHash, StringRef(arg));

    // Concurrent completions will block so that they have higher chance to use
    // the cached completion instance.
    std::lock_guard<std::mutex> lock(mtx);

    if (performCachedOperaitonIfPossible(Invocation, ArgsHash, completionBuffer,
                                         Offset, DiagC, Callback))
      return true;

    if (performNewOperation(ArgsHash, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  } else {
    // Concurrent completions may happen in parallel when caching is disabled.
    if (performNewOperation(None, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  }

  assert(!Error.empty());
  return false;
}
<|endoftext|>


<commit_before>//===--- LLVMSwiftAA.cpp - LLVM Alias Analysis for Swift ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/LLVMPasses/Passes.h"
#include "LLVMARCOpts.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"

using namespace llvm;
using swift::SwiftAAResult;
using swift::SwiftAAWrapperPass;

//===----------------------------------------------------------------------===//
//                           Alias Analysis Result
//===----------------------------------------------------------------------===//

llvm::ModRefInfo SwiftAAResult::getModRefInfo(llvm::ImmutableCallSite CS,
                                              const llvm::MemoryLocation &Loc) {
  // We know the mod-ref behavior of various runtime functions.
  switch (classifyInstruction(*CS.getInstruction())) {
  case RT_AllocObject:
  case RT_NoMemoryAccessed:
  case RT_Retain:
  case RT_RetainUnowned:
  case RT_CheckUnowned:
  case RT_ObjCRetain:
  case RT_BridgeRetain:
  case RT_UnknownRetain:
  case RT_RetainN:
  case RT_UnknownRetainN:
  case RT_BridgeRetainN:
  case RT_FixLifetime:
    // These entrypoints don't modify any compiler-visible state.
    return MRI_NoModRef;
  case RT_ReleaseN:
  case RT_UnknownReleaseN:
  case RT_BridgeReleaseN:
  case RT_Release:
  case RT_ObjCRelease:
  case RT_BridgeRelease:
  case RT_UnknownRelease:
  case RT_Unknown:
    break;
  }

  return AAResultBase::getModRefInfo(CS, Loc);
}

//===----------------------------------------------------------------------===//
//                        Alias Analysis Wrapper Pass
//===----------------------------------------------------------------------===//

char SwiftAAWrapperPass::ID = 0;
INITIALIZE_PASS_BEGIN(SwiftAAWrapperPass, "swift-aa",
                      "Swift Alias Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(SwiftAAWrapperPass, "swift-aa",
                    "Swift Alias Analysis", false, true)

SwiftAAWrapperPass::SwiftAAWrapperPass() : ImmutablePass(ID) {
  initializeSwiftAAWrapperPassPass(*PassRegistry::getPassRegistry());
}

bool SwiftAAWrapperPass::doInitialization(Module &M) {
  Result.reset(new SwiftAAResult());
  return false;
}

bool SwiftAAWrapperPass::doFinalization(Module &M) {
  Result.reset();
  return false;
}

void SwiftAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequired<TargetLibraryInfoWrapperPass>();
}

//===----------------------------------------------------------------------===//
//                           Top Level Entry Point
//===----------------------------------------------------------------------===//

llvm::ImmutablePass *swift::createSwiftAAWrapperPass() {
  return new SwiftAAWrapperPass();
}
<commit_msg>[semantic-arc] Use BaseModRef effects from LLVMSwift.def in LLVMSwiftAA instead of a switch.<commit_after>//===--- LLVMSwiftAA.cpp - LLVM Alias Analysis for Swift ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/LLVMPasses/Passes.h"
#include "LLVMARCOpts.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"

using namespace llvm;
using namespace swift;

//===----------------------------------------------------------------------===//
//                           Alias Analysis Result
//===----------------------------------------------------------------------===//

static ModRefInfo getConservativeModRefForKind(const llvm::Instruction &I) {
  switch (classifyInstruction(I)) {
#define KIND(Name, MemBehavior) case RT_ ## Name: return MRI_ ## MemBehavior;
#include "LLVMSwift.def"
  }
}

ModRefInfo SwiftAAResult::getModRefInfo(llvm::ImmutableCallSite CS,
                                        const llvm::MemoryLocation &Loc) {
  // We know at compile time that certain entry points do not modify any
  // compiler-visible state ever. Quickly check if we have one of those
  // instructions and return if so.
  if (MRI_NoModRef == getConservativeModRefForKind(*CS.getInstruction()))
    return MRI_NoModRef;

  // Otherwise, delegate to the rest of the AA ModRefInfo machinery.
  return AAResultBase::getModRefInfo(CS, Loc);
}

//===----------------------------------------------------------------------===//
//                        Alias Analysis Wrapper Pass
//===----------------------------------------------------------------------===//

char SwiftAAWrapperPass::ID = 0;
INITIALIZE_PASS_BEGIN(SwiftAAWrapperPass, "swift-aa",
                      "Swift Alias Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(SwiftAAWrapperPass, "swift-aa",
                    "Swift Alias Analysis", false, true)

SwiftAAWrapperPass::SwiftAAWrapperPass() : ImmutablePass(ID) {
  initializeSwiftAAWrapperPassPass(*PassRegistry::getPassRegistry());
}

bool SwiftAAWrapperPass::doInitialization(Module &M) {
  Result.reset(new SwiftAAResult());
  return false;
}

bool SwiftAAWrapperPass::doFinalization(Module &M) {
  Result.reset();
  return false;
}

void SwiftAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequired<TargetLibraryInfoWrapperPass>();
}

//===----------------------------------------------------------------------===//
//                           Top Level Entry Point
//===----------------------------------------------------------------------===//

llvm::ImmutablePass *swift::createSwiftAAWrapperPass() {
  return new SwiftAAWrapperPass();
}
<|endoftext|>