<commit_before>#ifndef ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__
#define ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__

#include <algorithm>
#include <limits>
#include <iterator>
#include <numeric>
#include <random>
#include <stdexcept>
#include <vector>

#include <aleph/geometry/RipsExpander.hh>

#include <aleph/geometry/distances/Traits.hh>

#include <aleph/math/SymmetricMatrix.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/topology/filtrations/Data.hh>

namespace aleph
{

namespace geometry
{

/**
  Builds a witness complex from a given container. This requires a set
  of *landmarks*. Other configuration options influence how a new edge
  will be created from the data.

  If you call this function with its barest minimum parameters by only
  specifying a container and a set of landmarks, the resulting complex
  will automatically adjust to your data and follows the definition of
  the paper:

    > Topological estimation using witness complexes\n
    > Vin de Silva and Gunnar Carlsson\n
    > Eurographics Symposium on Point-Based Graphics, 2004

  The other parameters, in particular \p R, permit tuning the results,
  thereby given the complex more "slack" when creating edges. However,
  this also increases the size of the complex.

  @param container Container for which to calculate the witness complex

  @param begin     Input iterator to begin of landmark range; landmarks
                   must be specified as *indices*. Each index has to be
                   valid for \p container.

  @param end       Input iterator to end of landmark range

  @param dimension Maximum dimension for expanding the witness complex
                   after obtaining its edges. The expansion process is
                   going to use the maximum possible dimension if this
                   parameter is not specified by the client.

  @param nu        \f$\nu\f$-parameter as defined in the paper. The
                   parameter controls which distance threshold is used
                   for creating an edge.\n

                   More precisely, an edge is created if the following
                   holds:\n
                   \n
                    \f[
                     \max(\mathrm{dist}_{a,i}\mathrm{dist}_{b,i}) \leq R + m_i
                    \f]
                   \n
                   Here, \f$m_i\f$ refers to the \f$\nu\f$th
                   smallest element of the distance matrix.

  @param R         Maximum radius parameter for determining whether to
                   create an edge or not. The default value makes sure
                   that *only* the distances between the landmarks and
                   the points will be used for edge creation.

  @param distance  Distance functor, e.g. the Euclidean distance, that
                   is used for calculating distances between landmarks
                   and data points. This parameter is provided to make
                   it possible for the compiler to detect the template
                   parameter \p distance automatically.

  @returns         Witness complex of the given container. Notice that
                   the complex is stored as a simplicial complex whose
                   data type and index type are derived from the input
                   data. The data of a simplex contains the *smallest*
                   threshold for which they appear in the complex. The
                   complex will be sorted according to this value.
*/

template <
  class Distance,
  class Container,
  class InputIterator
> auto buildWitnessComplex(
  const Container& container,
  InputIterator begin,
  InputIterator end,
  unsigned dimension = 0,
  unsigned nu = 2,
  typename Distance::ResultType R = typename Distance::ResultType(),
  Distance /* distance */ = Distance() ) -> topology::SimplicialComplex< topology::Simplex<typename Distance::ResultType, typename std::iterator_traits<InputIterator>::value_type> >
{
  using IndexType         = typename std::iterator_traits<InputIterator>::value_type;
  using VertexType        = IndexType;
  using DataType          = typename Distance::ResultType;
  using Traits            = aleph::geometry::distances::Traits<Distance>;
  using Simplex           = topology::Simplex<DataType, VertexType>;
  using SimplicialComplex = topology::SimplicialComplex<Simplex>;

  // These are only the *indices* of the landmarks, with respect to the
  // underlying point cloud.
  std::vector<IndexType> landmarkIndices( begin, end );

  auto n = landmarkIndices.size();
  auto N = container.size();
  auto d = container.dimension();

  // Much of the behaviour below will be undefined if we permit such
  // situations to occur.
  if( n == 0 || N == 0 )
    return {};

  // Distance matrix between a set of $n$ landmarks (cols) and $N$ data
  // points (rows). Note that I transposed the matrix because accessing
  // the columns is faster that way (and will be required later on).
  std::vector< std::vector<DataType> > D;
  D.reserve( N );

  Distance dist;
  Traits traits;

  for( std::size_t j = 0; j < N; j++ )
  {
    std::vector<DataType> distances;
    distances.reserve( n );

    auto&& point = container[j];

    for( std::size_t i = 0; i < n; i++ )
    {
      auto&& landmark = container[ landmarkIndices.at(i) ];

      distances.emplace_back( traits.from( dist( landmark.begin(), point.begin(), d ) ) );
    }

    D.push_back( distances );
  }

  // Get smallest entries of the distance matrix. This is required for
  // deciding whether a specific edge is valid or not, with respect to
  // the given parameters.

  std::vector<DataType> smallest( N );

  if( nu != 0 )
  {
    for( std::size_t col = 0; col < N; col++ )
    {
      std::vector<DataType> column = D[col];

      std::nth_element( column.begin(), column.begin() + nu - 1, column.end() );
      smallest[col] = column.at( nu - 1 );
    }
  }

  // -------------------------------------------------------------------
  //
  // Records the appearance times of each potential edge in the witness
  // complex and creates the valid edges.

  std::vector<Simplex> simplices;

  aleph::math::SymmetricMatrix<DataType> M( n );

  for( std::size_t i = 0; i < n; i++ )
  {
    simplices.push_back( Simplex( static_cast<VertexType>(i) ) );

    for( std::size_t j = i+1; j < n; j++ )
    {
      auto min = std::numeric_limits<DataType>::max();

      for( std::size_t k = 0; k < N; k++ )
      {
        if( std::max( D[k][i], D[k][j] ) <= R + smallest.at(k) )
          min = std::min( min, std::max( D[k][i], D[k][j] ) );
      }

      if( min != std::numeric_limits<DataType>::max() )
      {
        auto u = static_cast<VertexType>(i);
        auto v = static_cast<VertexType>(j);

        simplices.push_back( Simplex( {u,v}, min ) );
      }
    }
  }

  aleph::geometry::RipsExpander<SimplicialComplex> ripsExpander;

  SimplicialComplex K = SimplicialComplex( simplices.begin(), simplices.end() );
  SimplicialComplex L = ripsExpander( K, dimension == 0 ? static_cast<unsigned>( d + 1 ) : dimension );
  L                   = ripsExpander.assignMaximumWeight( L );

  L.sort( aleph::topology::filtrations::Data<Simplex>() );
  return L;
}

template <class T, class OutputIterator> void generateRandomLandmarks( T n, T k, OutputIterator result )
{
  std::random_device rd;
  std::mt19937 rng( rd() );

  std::vector<T> indices( n );

  using DifferenceType = typename std::vector<T>::difference_type;

  std::iota( indices.begin(), indices.end(), T() );
  std::shuffle( indices.begin(), indices.end(), rng );
  std::copy( indices.begin(), indices.begin() + static_cast<DifferenceType>(k), result );
}

template <
  class Distance,
  class Container,
  class OutputIterator
> void generateMaxMinLandmarks( const Container& container, std::size_t n, OutputIterator result, Distance distance = Distance() )
{
  if( n > container.size() )
    throw std::out_of_range( "Number of landmarks is out of range" );

  using SizeType = decltype( container.size() );

  std::random_device rd;
  std::mt19937 rng( rd() );

  std::uniform_int_distribution<SizeType> distribution( SizeType(0), container.size() - 1 );

  std::vector<SizeType> indices;
  indices.reserve( n );

  indices.emplace_back( distribution( rng ) );

  using DataType = typename Distance::ResultType;
  auto N         = container.size();
  auto d         = container.dimension();

  while( indices.size() < n )
  {
    auto index = SizeType(0);
    auto max   = std::numeric_limits<DataType>::lowest();

    for( SizeType i = 0; i < N; i++ )
    {
      auto min = std::numeric_limits<DataType>::max();

      for( auto&& landmarkIndex : indices )
      {
        auto dist = distance( container[i].begin(), container[landmarkIndex].begin(), d );
        min       = std::min( min, dist );
      }

      if( min > max )
      {
        max   = min;
        index = i;
      }
    }

    indices.push_back( index );
  }

  std::copy( indices.begin(), indices.end(), result );
}

} // namespace geometry

} // namespace aleph

#endif
<commit_msg>Documented witness complex landmark creation strategies<commit_after>#ifndef ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__
#define ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__

#include <algorithm>
#include <limits>
#include <iterator>
#include <numeric>
#include <random>
#include <stdexcept>
#include <vector>

#include <aleph/geometry/RipsExpander.hh>

#include <aleph/geometry/distances/Traits.hh>

#include <aleph/math/SymmetricMatrix.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/topology/filtrations/Data.hh>

namespace aleph
{

namespace geometry
{

/**
  Builds a witness complex from a given container. This requires a set
  of *landmarks*. Other configuration options influence how a new edge
  will be created from the data.

  If you call this function with its barest minimum parameters by only
  specifying a container and a set of landmarks, the resulting complex
  will automatically adjust to your data and follows the definition of
  the paper:

    > Topological estimation using witness complexes\n
    > Vin de Silva and Gunnar Carlsson\n
    > Eurographics Symposium on Point-Based Graphics, 2004

  The other parameters, in particular \p R, permit tuning the results,
  thereby given the complex more "slack" when creating edges. However,
  this also increases the size of the complex.

  @param container Container for which to calculate the witness complex

  @param begin     Input iterator to begin of landmark range; landmarks
                   must be specified as *indices*. Each index has to be
                   valid for \p container.

  @param end       Input iterator to end of landmark range

  @param dimension Maximum dimension for expanding the witness complex
                   after obtaining its edges. The expansion process is
                   going to use the maximum possible dimension if this
                   parameter is not specified by the client.

  @param nu        \f$\nu\f$-parameter as defined in the paper. The
                   parameter controls which distance threshold is used
                   for creating an edge.\n

                   More precisely, an edge is created if the following
                   holds:\n
                   \n
                    \f[
                     \max(\mathrm{dist}_{a,i}\mathrm{dist}_{b,i}) \leq R + m_i
                    \f]
                   \n
                   Here, \f$m_i\f$ refers to the \f$\nu\f$th
                   smallest element of the distance matrix.

  @param R         Maximum radius parameter for determining whether to
                   create an edge or not. The default value makes sure
                   that *only* the distances between the landmarks and
                   the points will be used for edge creation.

  @param distance  Distance functor, e.g. the Euclidean distance, that
                   is used for calculating distances between landmarks
                   and data points. This parameter is provided to make
                   it possible for the compiler to detect the template
                   parameter \p distance automatically.

  @returns         Witness complex of the given container. Notice that
                   the complex is stored as a simplicial complex whose
                   data type and index type are derived from the input
                   data. The data of a simplex contains the *smallest*
                   threshold for which they appear in the complex. The
                   complex will be sorted according to this value.
*/

template <
  class Distance,
  class Container,
  class InputIterator
> auto buildWitnessComplex(
  const Container& container,
  InputIterator begin,
  InputIterator end,
  unsigned dimension = 0,
  unsigned nu = 2,
  typename Distance::ResultType R = typename Distance::ResultType(),
  Distance /* distance */ = Distance() ) -> topology::SimplicialComplex< topology::Simplex<typename Distance::ResultType, typename std::iterator_traits<InputIterator>::value_type> >
{
  using IndexType         = typename std::iterator_traits<InputIterator>::value_type;
  using VertexType        = IndexType;
  using DataType          = typename Distance::ResultType;
  using Traits            = aleph::geometry::distances::Traits<Distance>;
  using Simplex           = topology::Simplex<DataType, VertexType>;
  using SimplicialComplex = topology::SimplicialComplex<Simplex>;

  // These are only the *indices* of the landmarks, with respect to the
  // underlying point cloud.
  std::vector<IndexType> landmarkIndices( begin, end );

  auto n = landmarkIndices.size();
  auto N = container.size();
  auto d = container.dimension();

  // Much of the behaviour below will be undefined if we permit such
  // situations to occur.
  if( n == 0 || N == 0 )
    return {};

  // Distance matrix between a set of $n$ landmarks (cols) and $N$ data
  // points (rows). Note that I transposed the matrix because accessing
  // the columns is faster that way (and will be required later on).
  std::vector< std::vector<DataType> > D;
  D.reserve( N );

  Distance dist;
  Traits traits;

  for( std::size_t j = 0; j < N; j++ )
  {
    std::vector<DataType> distances;
    distances.reserve( n );

    auto&& point = container[j];

    for( std::size_t i = 0; i < n; i++ )
    {
      auto&& landmark = container[ landmarkIndices.at(i) ];

      distances.emplace_back( traits.from( dist( landmark.begin(), point.begin(), d ) ) );
    }

    D.push_back( distances );
  }

  // Get smallest entries of the distance matrix. This is required for
  // deciding whether a specific edge is valid or not, with respect to
  // the given parameters.

  std::vector<DataType> smallest( N );

  if( nu != 0 )
  {
    for( std::size_t col = 0; col < N; col++ )
    {
      std::vector<DataType> column = D[col];

      std::nth_element( column.begin(), column.begin() + nu - 1, column.end() );
      smallest[col] = column.at( nu - 1 );
    }
  }

  // -------------------------------------------------------------------
  //
  // Records the appearance times of each potential edge in the witness
  // complex and creates the valid edges.

  std::vector<Simplex> simplices;

  aleph::math::SymmetricMatrix<DataType> M( n );

  for( std::size_t i = 0; i < n; i++ )
  {
    simplices.push_back( Simplex( static_cast<VertexType>(i) ) );

    for( std::size_t j = i+1; j < n; j++ )
    {
      auto min = std::numeric_limits<DataType>::max();

      for( std::size_t k = 0; k < N; k++ )
      {
        if( std::max( D[k][i], D[k][j] ) <= R + smallest.at(k) )
          min = std::min( min, std::max( D[k][i], D[k][j] ) );
      }

      if( min != std::numeric_limits<DataType>::max() )
      {
        auto u = static_cast<VertexType>(i);
        auto v = static_cast<VertexType>(j);

        simplices.push_back( Simplex( {u,v}, min ) );
      }
    }
  }

  aleph::geometry::RipsExpander<SimplicialComplex> ripsExpander;

  SimplicialComplex K = SimplicialComplex( simplices.begin(), simplices.end() );
  SimplicialComplex L = ripsExpander( K, dimension == 0 ? static_cast<unsigned>( d + 1 ) : dimension );
  L                   = ripsExpander.assignMaximumWeight( L );

  L.sort( aleph::topology::filtrations::Data<Simplex>() );
  return L;
}

/**
  Generates a random set of landmarks for use with the witness complex.
  Essentially, this function merely generates a set of *random indices*
  based on a random shuffle operation. The results of this are saved in
  an output iterator.

  @param n      Number of points
  @param k      Number of landmarks
  @param result Output iterator for storing the results
*/

template <class T, class OutputIterator> void generateRandomLandmarks( T n, T k, OutputIterator result )
{
  std::random_device rd;
  std::mt19937 rng( rd() );

  std::vector<T> indices( n );

  using DifferenceType = typename std::vector<T>::difference_type;

  std::iota( indices.begin(), indices.end(), T() );
  std::shuffle( indices.begin(), indices.end(), rng );
  std::copy( indices.begin(), indices.begin() + static_cast<DifferenceType>(k), result );
}

/**
  Generates a set of landmarks for the witness complex, using the
  max-min strategy. Given a distance measure, a new landmark will
  be chosen so as to *maximize* the *minimum distance* to the set
  of selected landmarks. An output iterator is used to report the
  indices of the selected landmarks.

  @param container Container that stores the input data
  @param n         Number of landmarks to select
  @param result    Output iterator for storing the results
  @param distance  Distance measure. This parameter may be specified
                   to permit template type deduction.
*/

template <
  class Distance,
  class Container,
  class OutputIterator
> void generateMaxMinLandmarks( const Container& container, std::size_t n, OutputIterator result, Distance distance = Distance() )
{
  if( n > container.size() )
    throw std::out_of_range( "Number of landmarks is out of range" );

  using SizeType = decltype( container.size() );

  std::random_device rd;
  std::mt19937 rng( rd() );

  std::uniform_int_distribution<SizeType> distribution( SizeType(0), container.size() - 1 );

  std::vector<SizeType> indices;
  indices.reserve( n );

  indices.emplace_back( distribution( rng ) );

  using DataType = typename Distance::ResultType;
  auto N         = container.size();
  auto d         = container.dimension();

  while( indices.size() < n )
  {
    auto index = SizeType(0);
    auto max   = std::numeric_limits<DataType>::lowest();

    for( SizeType i = 0; i < N; i++ )
    {
      auto min = std::numeric_limits<DataType>::max();

      for( auto&& landmarkIndex : indices )
      {
        auto dist = distance( container[i].begin(), container[landmarkIndex].begin(), d );
        min       = std::min( min, dist );
      }

      if( min > max )
      {
        max   = min;
        index = i;
      }
    }

    indices.push_back( index );
  }

  std::copy( indices.begin(), indices.end(), result );
}

} // namespace geometry

} // namespace aleph

#endif
<|endoftext|>


<commit_before>/*
 * This File is part of Davix, The IO library for HTTP based protocols
 * Copyright (C) 2013  Adrien Devresse <adrien.devresse@cern.ch>, CERN
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
*/

#ifndef DAVIX_HOOKS_IMPL_HPP
#define DAVIX_HOOKS_IMPL_HPP

#include <hooks/davix_hooks_fwd.hpp>

// intern file, Never use directly
#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace Davix{

struct ContextInternal;

#ifndef DAVIX_STD_CXX03

class HookList{
public:

    RequestPreRunHook _pre_run_req;

    RequestPreSendHook _pre_send_req;

    RequestPreReceHook _pre_rece_req;

private:
    HookList();
    friend class ContextInternal;
};

// define
template<typename HookType>
inline void hookDefine(HookList & c,  const HookType & hook){
    throw DavixException(std::string("davix::hook"), StatusCode::InvalidHook, "Invalid Hook type");
}

template<>
inline void hookDefine(HookList &c, const RequestPreRunHook & hook){
    c._pre_run_req = hook;
}

template<>
inline void hookDefine(HookList &c, const RequestPreSendHook & hook){
    c._pre_send_req = hook;
}

template<>
inline void hookDefine(HookList &c, const RequestPreReceHook & hook){
    c._pre_rece_req = hook;
}

// get
template<typename HookType>
inline const HookType & hookGet(HookList & c){
    throw DavixException(std::string("davix::hook"), StatusCode::InvalidHook, "Invalid Hook type");
}

template<>
inline const RequestPreRunHook & hookGet(HookList & c){
    return c._pre_run_req;
}

template<>
inline const RequestPreSendHook & hookGet(HookList & c){
    return c._pre_send_req;
}

template<>
inline const RequestPreReceHook & hookGet(HookList & c){
    return c._pre_rece_req;
}

#endif

}

#endif

#endif // DAVIX_HOOKS_IMPL_HPP
<commit_msg>- correct minor compilation warning on OSX<commit_after>/*
 * This File is part of Davix, The IO library for HTTP based protocols
 * Copyright (C) 2013  Adrien Devresse <adrien.devresse@cern.ch>, CERN
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
*/

#ifndef DAVIX_HOOKS_IMPL_HPP
#define DAVIX_HOOKS_IMPL_HPP

#include <hooks/davix_hooks_fwd.hpp>

// intern file, Never use directly
#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace Davix{

struct ContextInternal;

#ifndef DAVIX_STD_CXX03

class HookList{
public:

    RequestPreRunHook _pre_run_req;

    RequestPreSendHook _pre_send_req;

    RequestPreReceHook _pre_rece_req;

private:
    HookList();
    friend struct ContextInternal;
};

// define
template<typename HookType>
inline void hookDefine(HookList & c,  const HookType & hook){
    throw DavixException(std::string("davix::hook"), StatusCode::InvalidHook, "Invalid Hook type");
}

template<>
inline void hookDefine(HookList &c, const RequestPreRunHook & hook){
    c._pre_run_req = hook;
}

template<>
inline void hookDefine(HookList &c, const RequestPreSendHook & hook){
    c._pre_send_req = hook;
}

template<>
inline void hookDefine(HookList &c, const RequestPreReceHook & hook){
    c._pre_rece_req = hook;
}

// get
template<typename HookType>
inline const HookType & hookGet(HookList & c){
    throw DavixException(std::string("davix::hook"), StatusCode::InvalidHook, "Invalid Hook type");
}

template<>
inline const RequestPreRunHook & hookGet(HookList & c){
    return c._pre_run_req;
}

template<>
inline const RequestPreSendHook & hookGet(HookList & c){
    return c._pre_send_req;
}

template<>
inline const RequestPreReceHook & hookGet(HookList & c){
    return c._pre_rece_req;
}

#endif

}

#endif

#endif // DAVIX_HOOKS_IMPL_HPP
<|endoftext|>


<commit_before><commit_msg>prevent invalid OOXML files with trendlines, related #i88825#<commit_after><|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreGLFrameBufferObject.h"
#include "OgreGLPixelFormat.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreRoot.h"
#include "OgreGLHardwarePixelBuffer.h"
#include "OgreGLFBORenderTexture.h"

namespace Ogre {

//-----------------------------------------------------------------------------
    GLFrameBufferObject::GLFrameBufferObject(GLFBOManager *manager, uint fsaa):
        mManager(manager), mNumSamples(fsaa)
    {
        /// Generate framebuffer object
        glGenFramebuffersEXT(1, &mFB);
		// check multisampling
		if (GLEW_EXT_framebuffer_blit && GLEW_EXT_framebuffer_multisample)
		{
			// check samples supported
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
			GLint maxSamples;
			glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
			mNumSamples = std::min(mNumSamples, (GLsizei)maxSamples);
		}
		else
		{
			mNumSamples = 0;
		}
		// will we need a second FBO to do multisampling?
		if (mNumSamples)
		{
			glGenFramebuffersEXT(1, &mMultisampleFB);
		}
		else
		{
			mMultisampleFB = 0;
		}
        /// Initialise state
        mDepth.buffer=0;
        mStencil.buffer=0;
        for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
        {
            mColour[x].buffer=0;
        }
    }
    GLFrameBufferObject::~GLFrameBufferObject()
    {
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
		mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        /// Delete framebuffer object
        glDeleteFramebuffersEXT(1, &mFB);
		if (mMultisampleFB)
			glDeleteFramebuffersEXT(1, &mMultisampleFB);

    }
    void GLFrameBufferObject::bindSurface(size_t attachment, const GLSurfaceDesc &target)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment] = target;
		// Re-initialise
		if(mColour[0].buffer)
			initialise();
    }
    void GLFrameBufferObject::unbindSurface(size_t attachment)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment].buffer = 0;
		// Re-initialise if buffer 0 still bound
		if(mColour[0].buffer)
		{
			initialise();
		}
    }
    void GLFrameBufferObject::initialise()
    {
		// Release depth and stencil, if they were bound
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
		mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        /// First buffer must be bound
        if(!mColour[0].buffer)
        {
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
            "Attachment 0 must have surface attached",
		 	"GLFrameBufferObject::initialise");
        }

		// If we're doing multisampling, then we need another FBO which contains a
		// renderbuffer which is set up to multisample, and we'll blit it to the final
		// FBO afterwards to perform the multisample resolve. In that case, the
		// mMultisampleFB is bound during rendering and is the one with a depth/stencil

        /// Store basic stats
        size_t width = mColour[0].buffer->getWidth();
        size_t height = mColour[0].buffer->getHeight();
        GLuint format = mColour[0].buffer->getGLFormat();
        PixelFormat ogreFormat = mColour[0].buffer->getFormat();

		// Bind simple buffer to add colour attachments
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);

        /// Bind all attachment points to frame buffer
        for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
        {
            if(mColour[x].buffer)
            {
                if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible size ";
                    ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight();
                    ss << ". It must be of the same as the size of surface 0, ";
                    ss << width << "x" << height;
                    ss << ".";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
                }
                if(mColour[x].buffer->getGLFormat() != format)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible format.";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
                }
	            mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT+x, mColour[x].zoffset);
            }
            else
            {
                // Detach
                glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+x,
                    GL_RENDERBUFFER_EXT, 0);
            }
        }

		// Now deal with depth / stencil
		if (mMultisampleFB)
		{
			// Bind multisample buffer
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mMultisampleFB);

			// Create AA render buffer (colour)
			// note, this can be shared too because we blit it to the final FBO
			// right after the render is finished
			mMultisampleColourBuffer = mManager->requestRenderBuffer(format, width, height, mNumSamples);

			// Attach it, because we won't be attaching below and non-multisample has
			// actually been attached to other FBO
			mMultisampleColourBuffer.buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT,
				mMultisampleColourBuffer.zoffset);

			// depth & stencil will be dealt with below

		}

        /// Find suitable depth and stencil format that is compatible with colour format
        GLenum depthFormat, stencilFormat;
        mManager->getBestDepthStencil(ogreFormat, &depthFormat, &stencilFormat);

        /// Request surfaces
        mDepth = mManager->requestRenderBuffer(depthFormat, width, height, mNumSamples);
		if (depthFormat == GL_DEPTH24_STENCIL8_EXT)
		{
			// bind same buffer to depth and stencil attachments
            mManager->requestRenderBuffer(mDepth);
			mStencil = mDepth;
		}
		else
		{
			// separate stencil
			mStencil = mManager->requestRenderBuffer(stencilFormat, width, height, mNumSamples);
		}

        /// Attach/detach surfaces
        if(mDepth.buffer)
        {
            mDepth.buffer->bindToFramebuffer(GL_DEPTH_ATTACHMENT_EXT, mDepth.zoffset);
        }
        else
        {
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
                GL_RENDERBUFFER_EXT, 0);
        }
        if(mStencil.buffer)
        {
            mStencil.buffer->bindToFramebuffer(GL_STENCIL_ATTACHMENT_EXT, mStencil.zoffset);
        }
        else
        {
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
                GL_RENDERBUFFER_EXT, 0);
        }

		/// Do glDrawBuffer calls
		GLenum bufs[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
		GLsizei n=0;
		for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
		{
			// Fill attached colour buffers
			if(mColour[x].buffer)
			{
				bufs[x] = GL_COLOR_ATTACHMENT0_EXT + x;
				// Keep highest used buffer + 1
				n = x+1;
			}
			else
			{
				bufs[x] = GL_NONE;
			}
		}
		if(glDrawBuffers)
		{
			/// Drawbuffer extension supported, use it
			glDrawBuffers(n, bufs);
		}
		else
		{
			/// In this case, the capabilities will not show more than 1 simultaneaous render target.
			glDrawBuffer(bufs[0]);
		}
		if (mMultisampleFB)
		{
			// we need a read buffer because we'll be blitting to mFB
			glReadBuffer(bufs[0]);
		}
		else
		{
			/// No read buffer, by default, if we want to read anyway we must not forget to set this.
			glReadBuffer(GL_NONE);
		}

        /// Check status
        GLuint status;
        status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

        /// Bind main buffer
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

        switch(status)
        {
        case GL_FRAMEBUFFER_COMPLETE_EXT:
            // All is good
            break;
        case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
            "All framebuffer formats with this texture internal format unsupported",
		 	"GLFrameBufferObject::initialise");
        default:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
            "Framebuffer incomplete or other FBO status error",
		 	"GLFrameBufferObject::initialise");
        }

    }
    void GLFrameBufferObject::bind()
    {
        /// Bind it to FBO
		if (mMultisampleFB)
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mMultisampleFB);
		else
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
    }

	void GLFrameBufferObject::swapBuffers()
	{
		if (mMultisampleFB)
		{
			// blit from multisample buffer to final buffer, triggers resolve
			size_t width = mColour[0].buffer->getWidth();
			size_t height = mColour[0].buffer->getHeight();
			glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mMultisampleFB);
			glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFB);
			glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

		}
	}

    size_t GLFrameBufferObject::getWidth()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getWidth();
    }
    size_t GLFrameBufferObject::getHeight()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getHeight();
    }
    PixelFormat GLFrameBufferObject::getFormat()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getFormat();
    }
//-----------------------------------------------------------------------------
}
<commit_msg>GL: Only bind up to the max supported number of render targets since not all implementations support 8.  This prevents a few OpenGL errors.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreGLFrameBufferObject.h"
#include "OgreGLPixelFormat.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreRoot.h"
#include "OgreGLHardwarePixelBuffer.h"
#include "OgreGLFBORenderTexture.h"

namespace Ogre {

//-----------------------------------------------------------------------------
    GLFrameBufferObject::GLFrameBufferObject(GLFBOManager *manager, uint fsaa):
        mManager(manager), mNumSamples(fsaa)
    {
        /// Generate framebuffer object
        glGenFramebuffersEXT(1, &mFB);
		// check multisampling
		if (GLEW_EXT_framebuffer_blit && GLEW_EXT_framebuffer_multisample)
		{
			// check samples supported
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
			GLint maxSamples;
			glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
			mNumSamples = std::min(mNumSamples, (GLsizei)maxSamples);
		}
		else
		{
			mNumSamples = 0;
		}
		// will we need a second FBO to do multisampling?
		if (mNumSamples)
		{
			glGenFramebuffersEXT(1, &mMultisampleFB);
		}
		else
		{
			mMultisampleFB = 0;
		}
        /// Initialise state
        mDepth.buffer=0;
        mStencil.buffer=0;
        for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
        {
            mColour[x].buffer=0;
        }
    }
    GLFrameBufferObject::~GLFrameBufferObject()
    {
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
		mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        /// Delete framebuffer object
        glDeleteFramebuffersEXT(1, &mFB);
		if (mMultisampleFB)
			glDeleteFramebuffersEXT(1, &mMultisampleFB);

    }
    void GLFrameBufferObject::bindSurface(size_t attachment, const GLSurfaceDesc &target)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment] = target;
		// Re-initialise
		if(mColour[0].buffer)
			initialise();
    }
    void GLFrameBufferObject::unbindSurface(size_t attachment)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment].buffer = 0;
		// Re-initialise if buffer 0 still bound
		if(mColour[0].buffer)
		{
			initialise();
		}
    }
    void GLFrameBufferObject::initialise()
    {
		// Release depth and stencil, if they were bound
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
		mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        /// First buffer must be bound
        if(!mColour[0].buffer)
        {
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
            "Attachment 0 must have surface attached",
		 	"GLFrameBufferObject::initialise");
        }

		// If we're doing multisampling, then we need another FBO which contains a
		// renderbuffer which is set up to multisample, and we'll blit it to the final
		// FBO afterwards to perform the multisample resolve. In that case, the
		// mMultisampleFB is bound during rendering and is the one with a depth/stencil

        /// Store basic stats
        size_t width = mColour[0].buffer->getWidth();
        size_t height = mColour[0].buffer->getHeight();
        GLuint format = mColour[0].buffer->getGLFormat();
        PixelFormat ogreFormat = mColour[0].buffer->getFormat();
        ushort maxSupportedMRTs = Root::getSingleton().getRenderSystem()->getCapabilities()->getNumMultiRenderTargets();

		// Bind simple buffer to add colour attachments
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);

        /// Bind all attachment points to frame buffer
        for(size_t x=0; x<maxSupportedMRTs; ++x)
        {
            if(mColour[x].buffer)
            {
                if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible size ";
                    ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight();
                    ss << ". It must be of the same as the size of surface 0, ";
                    ss << width << "x" << height;
                    ss << ".";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
                }
                if(mColour[x].buffer->getGLFormat() != format)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible format.";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
                }
	            mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT+x, mColour[x].zoffset);
            }
            else
            {
                // Detach
                glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+x,
                    GL_RENDERBUFFER_EXT, 0);
            }
        }

		// Now deal with depth / stencil
		if (mMultisampleFB)
		{
			// Bind multisample buffer
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mMultisampleFB);

			// Create AA render buffer (colour)
			// note, this can be shared too because we blit it to the final FBO
			// right after the render is finished
			mMultisampleColourBuffer = mManager->requestRenderBuffer(format, width, height, mNumSamples);

			// Attach it, because we won't be attaching below and non-multisample has
			// actually been attached to other FBO
			mMultisampleColourBuffer.buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT,
				mMultisampleColourBuffer.zoffset);

			// depth & stencil will be dealt with below

		}

        /// Find suitable depth and stencil format that is compatible with colour format
        GLenum depthFormat, stencilFormat;
        mManager->getBestDepthStencil(ogreFormat, &depthFormat, &stencilFormat);

        /// Request surfaces
        mDepth = mManager->requestRenderBuffer(depthFormat, width, height, mNumSamples);
		if (depthFormat == GL_DEPTH24_STENCIL8_EXT)
		{
			// bind same buffer to depth and stencil attachments
            mManager->requestRenderBuffer(mDepth);
			mStencil = mDepth;
		}
		else
		{
			// separate stencil
			mStencil = mManager->requestRenderBuffer(stencilFormat, width, height, mNumSamples);
		}

        /// Attach/detach surfaces
        if(mDepth.buffer)
        {
            mDepth.buffer->bindToFramebuffer(GL_DEPTH_ATTACHMENT_EXT, mDepth.zoffset);
        }
        else
        {
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
                GL_RENDERBUFFER_EXT, 0);
        }
        if(mStencil.buffer)
        {
            mStencil.buffer->bindToFramebuffer(GL_STENCIL_ATTACHMENT_EXT, mStencil.zoffset);
        }
        else
        {
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
                GL_RENDERBUFFER_EXT, 0);
        }

		/// Do glDrawBuffer calls
		GLenum bufs[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
		GLsizei n=0;
		for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
		{
			// Fill attached colour buffers
			if(mColour[x].buffer)
			{
				bufs[x] = GL_COLOR_ATTACHMENT0_EXT + x;
				// Keep highest used buffer + 1
				n = x+1;
			}
			else
			{
				bufs[x] = GL_NONE;
			}
		}
		if(glDrawBuffers)
		{
			/// Drawbuffer extension supported, use it
			glDrawBuffers(n, bufs);
		}
		else
		{
			/// In this case, the capabilities will not show more than 1 simultaneaous render target.
			glDrawBuffer(bufs[0]);
		}
		if (mMultisampleFB)
		{
			// we need a read buffer because we'll be blitting to mFB
			glReadBuffer(bufs[0]);
		}
		else
		{
			/// No read buffer, by default, if we want to read anyway we must not forget to set this.
			glReadBuffer(GL_NONE);
		}

        /// Check status
        GLuint status;
        status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

        /// Bind main buffer
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

        switch(status)
        {
        case GL_FRAMEBUFFER_COMPLETE_EXT:
            // All is good
            break;
        case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
            "All framebuffer formats with this texture internal format unsupported",
		 	"GLFrameBufferObject::initialise");
        default:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
            "Framebuffer incomplete or other FBO status error",
		 	"GLFrameBufferObject::initialise");
        }

    }
    void GLFrameBufferObject::bind()
    {
        /// Bind it to FBO
		if (mMultisampleFB)
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mMultisampleFB);
		else
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
    }

	void GLFrameBufferObject::swapBuffers()
	{
		if (mMultisampleFB)
		{
			// blit from multisample buffer to final buffer, triggers resolve
			size_t width = mColour[0].buffer->getWidth();
			size_t height = mColour[0].buffer->getHeight();
			glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mMultisampleFB);
			glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFB);
			glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

		}
	}

    size_t GLFrameBufferObject::getWidth()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getWidth();
    }
    size_t GLFrameBufferObject::getHeight()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getHeight();
    }
    PixelFormat GLFrameBufferObject::getFormat()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getFormat();
    }
//-----------------------------------------------------------------------------
}
<|endoftext|>


<commit_before>//===--- Backend.cpp - Interface to LLVM backend technologies -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ASTConsumers.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Driver/CompileOptions.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"

using namespace clang;
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN BackendConsumer  : public ASTConsumer {
    BackendAction Action;
    CompileOptions CompileOpts;
    const std::string &InputFile;
    std::string OutputFile;
    bool GenerateDebugInfo;

    llvm::OwningPtr<CodeGenerator> Gen;

    llvm::Module *TheModule;
    llvm::TargetData *TheTargetData;
    llvm::raw_ostream *AsmOutStream;

    mutable llvm::ModuleProvider *ModuleProvider;
    mutable FunctionPassManager *CodeGenPasses;
    mutable PassManager *PerModulePasses;
    mutable FunctionPassManager *PerFunctionPasses;

    FunctionPassManager *getCodeGenPasses() const;
    PassManager *getPerModulePasses() const;
    FunctionPassManager *getPerFunctionPasses() const;

    void CreatePasses();

    /// AddEmitPasses - Add passes necessary to emit assembly or LLVM
    /// IR.
    ///
    /// \return True on success. On failure \arg Error will be set to
    /// a user readable error message.
    bool AddEmitPasses(std::string &Error);

    void EmitAssembly();

  public:
    BackendConsumer(BackendAction action, Diagnostic &Diags,
                    const LangOptions &Features, const CompileOptions &compopts,
                    const std::string& infile, const std::string& outfile,
                    bool debug)  :
      Action(action),
      CompileOpts(compopts),
      InputFile(infile),
      OutputFile(outfile),
      GenerateDebugInfo(debug),
      Gen(CreateLLVMCodeGen(Diags, Features, InputFile, GenerateDebugInfo)),
      TheModule(0), TheTargetData(0), AsmOutStream(0), ModuleProvider(0),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}

    ~BackendConsumer() {
      delete AsmOutStream;
      delete TheTargetData;
      delete ModuleProvider;
      delete CodeGenPasses;
      delete PerModulePasses;
      delete PerFunctionPasses;
    }

    virtual void InitializeTU(TranslationUnit& TU) {
      Gen->InitializeTU(TU);

      TheModule = Gen->GetModule();
      ModuleProvider = new ExistingModuleProvider(TheModule);
      TheTargetData =
        new llvm::TargetData(TU.getContext().Target.getTargetDescription());
    }

    virtual void HandleTopLevelDecl(Decl *D) {
      Gen->HandleTopLevelDecl(D);
    }

    virtual void HandleTranslationUnit(TranslationUnit& TU) {
      Gen->HandleTranslationUnit(TU);

      EmitAssembly();
      // Force a flush here in case we never get released.
      if (AsmOutStream)
        AsmOutStream->flush();
    }

    virtual void HandleTagDeclDefinition(TagDecl *D) {
      Gen->HandleTagDeclDefinition(D);
    }
  };
}

FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
  if (!CodeGenPasses) {
    CodeGenPasses = new FunctionPassManager(ModuleProvider);
    CodeGenPasses->add(new TargetData(*TheTargetData));
  }

  return CodeGenPasses;
}

PassManager *BackendConsumer::getPerModulePasses() const {
  if (!PerModulePasses) {
    PerModulePasses = new PassManager();
    PerModulePasses->add(new TargetData(*TheTargetData));
  }

  return PerModulePasses;
}

FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
  if (!PerFunctionPasses) {
    PerFunctionPasses = new FunctionPassManager(ModuleProvider);
    PerFunctionPasses->add(new TargetData(*TheTargetData));
  }

  return PerFunctionPasses;
}

bool BackendConsumer::AddEmitPasses(std::string &Error) {
  if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
    AsmOutStream = new raw_stdout_ostream();
    sys::Program::ChangeStdoutToBinary();
  } else {
    if (OutputFile.empty()) {
      llvm::sys::Path Path(InputFile);
      Path.eraseSuffix();
      if (Action == Backend_EmitBC) {
        Path.appendSuffix("bc");
      } else if (Action == Backend_EmitLL) {
        Path.appendSuffix("ll");
      } else {
        Path.appendSuffix("s");
      }
      OutputFile = Path.toString();
    }

    AsmOutStream = new raw_fd_ostream(OutputFile.c_str(), true, Error);
    if (!Error.empty())
      return false;
  }

  if (Action == Backend_EmitBC) {
    getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream));
  } else if (Action == Backend_EmitLL) {
    getPerModulePasses()->add(createPrintModulePass(AsmOutStream));
  } else {
    bool Fast = CompileOpts.OptimizationLevel == 0;

    // Create the TargetMachine for generating code.
    const TargetMachineRegistry::entry *TME =
      TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error);
    if (!TME) {
      Error = std::string("Unable to get target machine: ") + Error;
      return false;
    }

    // FIXME: Support features?
    std::string FeatureStr;
    TargetMachine *TM = TME->CtorFn(*TheModule, FeatureStr);

    // Set register scheduler & allocation policy.
    RegisterScheduler::setDefault(createDefaultScheduler);
    RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
                                 createLinearScanRegisterAllocator);

    // From llvm-gcc:
    // If there are passes we have to run on the entire module, we do codegen
    // as a separate "pass" after that happens.
    // FIXME: This is disabled right now until bugs can be worked out.  Reenable
    // this for fast -O0 compiles!
    FunctionPassManager *PM = getCodeGenPasses();

    // Normal mode, emit a .s file by running the code generator.
    // Note, this also adds codegenerator level optimization passes.
    switch (TM->addPassesToEmitFile(*PM, *AsmOutStream,
                                    TargetMachine::AssemblyFile, Fast)) {
    default:
    case FileModel::Error:
      Error = "Unable to interface with target machine!\n";
      return false;
    case FileModel::AsmFile:
      break;
    }

    if (TM->addPassesToEmitFileFinish(*CodeGenPasses, 0, Fast)) {
      Error = "Unable to interface with target machine!\n";
      return false;
    }
  }

  return true;
}

void BackendConsumer::CreatePasses() {
  // In -O0 if checking is disabled, we don't even have per-function passes.
  if (CompileOpts.VerifyModule)
    getPerFunctionPasses()->add(createVerifierPass());

  if (CompileOpts.OptimizationLevel > 0) {
    FunctionPassManager *PM = getPerFunctionPasses();
    PM->add(createCFGSimplificationPass());
    if (CompileOpts.OptimizationLevel == 1)
      PM->add(createPromoteMemoryToRegisterPass());
    else
      PM->add(createScalarReplAggregatesPass());
    PM->add(createInstructionCombiningPass());
  }

  // For now we always create per module passes.
  PassManager *PM = getPerModulePasses();
  if (CompileOpts.OptimizationLevel > 0) {
    if (CompileOpts.UnitAtATime)
      PM->add(createRaiseAllocationsPass());      // call %malloc -> malloc inst
    PM->add(createCFGSimplificationPass());       // Clean up disgusting code
    PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas
    if (CompileOpts.UnitAtATime) {
      PM->add(createGlobalOptimizerPass());       // Optimize out global vars
      PM->add(createGlobalDCEPass());             // Remove unused fns and globs
      PM->add(createIPConstantPropagationPass()); // IP Constant Propagation
      PM->add(createDeadArgEliminationPass());    // Dead argument elimination
    }
    PM->add(createInstructionCombiningPass());    // Clean up after IPCP & DAE
    PM->add(createCFGSimplificationPass());       // Clean up after IPCP & DAE
    if (CompileOpts.UnitAtATime) {
      PM->add(createPruneEHPass());               // Remove dead EH info
      PM->add(createFunctionAttrsPass());         // Set readonly/readnone attrs
    }
    if (CompileOpts.InlineFunctions)
      PM->add(createFunctionInliningPass());      // Inline small functions
    else
      PM->add(createAlwaysInlinerPass());         // Respect always_inline
    if (CompileOpts.OptimizationLevel > 2)
      PM->add(createArgumentPromotionPass());     // Scalarize uninlined fn args
    if (CompileOpts.SimplifyLibCalls)
      PM->add(createSimplifyLibCallsPass());      // Library Call Optimizations
    PM->add(createInstructionCombiningPass());    // Cleanup for scalarrepl.
    PM->add(createJumpThreadingPass());           // Thread jumps.
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createScalarReplAggregatesPass());    // Break up aggregate allocas
    PM->add(createInstructionCombiningPass());    // Combine silly seq's
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createTailCallEliminationPass());     // Eliminate tail calls
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createReassociatePass());             // Reassociate expressions
    PM->add(createLoopRotatePass());              // Rotate Loop
    PM->add(createLICMPass());                    // Hoist loop invariants
    PM->add(createLoopUnswitchPass(CompileOpts.OptimizeSize ? true : false));
//    PM->add(createLoopIndexSplitPass());          // Split loop index
    PM->add(createInstructionCombiningPass());
    PM->add(createIndVarSimplifyPass());          // Canonicalize indvars
    PM->add(createLoopDeletionPass());            // Delete dead loops
    if (CompileOpts.UnrollLoops)
      PM->add(createLoopUnrollPass());            // Unroll small loops
    PM->add(createInstructionCombiningPass());    // Clean up after the unroller
    PM->add(createGVNPass());                     // Remove redundancies
    PM->add(createMemCpyOptPass());               // Remove memcpy / form memset
    PM->add(createSCCPPass());                    // Constant prop with SCCP

    // Run instcombine after redundancy elimination to exploit opportunities
    // opened up by them.
    PM->add(createInstructionCombiningPass());
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createDeadStoreEliminationPass());    // Delete dead stores
    PM->add(createAggressiveDCEPass());           // Delete dead instructions
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs

    if (CompileOpts.UnitAtATime) {
      PM->add(createStripDeadPrototypesPass());   // Get rid of dead prototypes
      PM->add(createDeadTypeEliminationPass());   // Eliminate dead types
    }

    if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
      PM->add(createConstantMergePass());         // Merge dup global constants
  } else {
    PM->add(createAlwaysInlinerPass());
  }
}

/// EmitAssembly - Handle interaction with LLVM backend to generate
/// actual machine code.
void BackendConsumer::EmitAssembly() {
  // Silently ignore if we weren't initialized for some reason.
  if (!TheModule || !TheTargetData)
    return;

  // Make sure IR generation is happy with the module. This is
  // released by the module provider.
  Module *M = Gen->ReleaseModule();
  if (!M) {
    // The module has been released by IR gen on failures, do not
    // double free.
    ModuleProvider->releaseModule();
    TheModule = 0;
    return;
  }

  assert(TheModule == M && "Unexpected module change during IR generation");

  CreatePasses();

  std::string Error;
  if (!AddEmitPasses(Error)) {
    // FIXME: Don't fail this way.
    llvm::cerr << "ERROR: " << Error << "\n";
    ::exit(1);
  }

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PerFunctionPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses)
    PerModulePasses->run(*M);

  if (CodeGenPasses) {
    CodeGenPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        CodeGenPasses->run(*I);
    CodeGenPasses->doFinalization();
  }
}

ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
                                          Diagnostic &Diags,
                                          const LangOptions &Features,
                                          const CompileOptions &CompileOpts,
                                          const std::string& InFile,
                                          const std::string& OutFile,
                                          bool GenerateDebugInfo) {
  return new BackendConsumer(Action, Diags, Features, CompileOpts,
                             InFile, OutFile, GenerateDebugInfo);
}
<commit_msg>for now, disable all debug info generation at -O1 and above.  This mirrors similar logic in llvm-gcc and will hopefully be fixed soon.<commit_after>//===--- Backend.cpp - Interface to LLVM backend technologies -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ASTConsumers.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Driver/CompileOptions.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"

using namespace clang;
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN BackendConsumer  : public ASTConsumer {
    BackendAction Action;
    CompileOptions CompileOpts;
    const std::string &InputFile;
    std::string OutputFile;
    bool GenerateDebugInfo;

    llvm::OwningPtr<CodeGenerator> Gen;

    llvm::Module *TheModule;
    llvm::TargetData *TheTargetData;
    llvm::raw_ostream *AsmOutStream;

    mutable llvm::ModuleProvider *ModuleProvider;
    mutable FunctionPassManager *CodeGenPasses;
    mutable PassManager *PerModulePasses;
    mutable FunctionPassManager *PerFunctionPasses;

    FunctionPassManager *getCodeGenPasses() const;
    PassManager *getPerModulePasses() const;
    FunctionPassManager *getPerFunctionPasses() const;

    void CreatePasses();

    /// AddEmitPasses - Add passes necessary to emit assembly or LLVM
    /// IR.
    ///
    /// \return True on success. On failure \arg Error will be set to
    /// a user readable error message.
    bool AddEmitPasses(std::string &Error);

    void EmitAssembly();

  public:
    BackendConsumer(BackendAction action, Diagnostic &Diags,
                    const LangOptions &Features, const CompileOptions &compopts,
                    const std::string& infile, const std::string& outfile,
                    bool debug)  :
      Action(action),
      CompileOpts(compopts),
      InputFile(infile),
      OutputFile(outfile),
      GenerateDebugInfo(debug),
      Gen(CreateLLVMCodeGen(Diags, Features, InputFile, GenerateDebugInfo)),
      TheModule(0), TheTargetData(0), AsmOutStream(0), ModuleProvider(0),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}

    ~BackendConsumer() {
      delete AsmOutStream;
      delete TheTargetData;
      delete ModuleProvider;
      delete CodeGenPasses;
      delete PerModulePasses;
      delete PerFunctionPasses;
    }

    virtual void InitializeTU(TranslationUnit& TU) {
      Gen->InitializeTU(TU);

      TheModule = Gen->GetModule();
      ModuleProvider = new ExistingModuleProvider(TheModule);
      TheTargetData =
        new llvm::TargetData(TU.getContext().Target.getTargetDescription());
    }

    virtual void HandleTopLevelDecl(Decl *D) {
      Gen->HandleTopLevelDecl(D);
    }

    virtual void HandleTranslationUnit(TranslationUnit& TU) {
      Gen->HandleTranslationUnit(TU);

      EmitAssembly();
      // Force a flush here in case we never get released.
      if (AsmOutStream)
        AsmOutStream->flush();
    }

    virtual void HandleTagDeclDefinition(TagDecl *D) {
      Gen->HandleTagDeclDefinition(D);
    }
  };
}

FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
  if (!CodeGenPasses) {
    CodeGenPasses = new FunctionPassManager(ModuleProvider);
    CodeGenPasses->add(new TargetData(*TheTargetData));
  }

  return CodeGenPasses;
}

PassManager *BackendConsumer::getPerModulePasses() const {
  if (!PerModulePasses) {
    PerModulePasses = new PassManager();
    PerModulePasses->add(new TargetData(*TheTargetData));
  }

  return PerModulePasses;
}

FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
  if (!PerFunctionPasses) {
    PerFunctionPasses = new FunctionPassManager(ModuleProvider);
    PerFunctionPasses->add(new TargetData(*TheTargetData));
  }

  return PerFunctionPasses;
}

bool BackendConsumer::AddEmitPasses(std::string &Error) {
  if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
    AsmOutStream = new raw_stdout_ostream();
    sys::Program::ChangeStdoutToBinary();
  } else {
    if (OutputFile.empty()) {
      llvm::sys::Path Path(InputFile);
      Path.eraseSuffix();
      if (Action == Backend_EmitBC) {
        Path.appendSuffix("bc");
      } else if (Action == Backend_EmitLL) {
        Path.appendSuffix("ll");
      } else {
        Path.appendSuffix("s");
      }
      OutputFile = Path.toString();
    }

    AsmOutStream = new raw_fd_ostream(OutputFile.c_str(), true, Error);
    if (!Error.empty())
      return false;
  }

  if (Action == Backend_EmitBC) {
    getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream));
  } else if (Action == Backend_EmitLL) {
    getPerModulePasses()->add(createPrintModulePass(AsmOutStream));
  } else {
    bool Fast = CompileOpts.OptimizationLevel == 0;

    // Create the TargetMachine for generating code.
    const TargetMachineRegistry::entry *TME =
      TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error);
    if (!TME) {
      Error = std::string("Unable to get target machine: ") + Error;
      return false;
    }

    // FIXME: Support features?
    std::string FeatureStr;
    TargetMachine *TM = TME->CtorFn(*TheModule, FeatureStr);

    // Set register scheduler & allocation policy.
    RegisterScheduler::setDefault(createDefaultScheduler);
    RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
                                 createLinearScanRegisterAllocator);

    // From llvm-gcc:
    // If there are passes we have to run on the entire module, we do codegen
    // as a separate "pass" after that happens.
    // FIXME: This is disabled right now until bugs can be worked out.  Reenable
    // this for fast -O0 compiles!
    FunctionPassManager *PM = getCodeGenPasses();

    // Normal mode, emit a .s file by running the code generator.
    // Note, this also adds codegenerator level optimization passes.
    switch (TM->addPassesToEmitFile(*PM, *AsmOutStream,
                                    TargetMachine::AssemblyFile, Fast)) {
    default:
    case FileModel::Error:
      Error = "Unable to interface with target machine!\n";
      return false;
    case FileModel::AsmFile:
      break;
    }

    if (TM->addPassesToEmitFileFinish(*CodeGenPasses, 0, Fast)) {
      Error = "Unable to interface with target machine!\n";
      return false;
    }
  }

  return true;
}

void BackendConsumer::CreatePasses() {
  // In -O0 if checking is disabled, we don't even have per-function passes.
  if (CompileOpts.VerifyModule)
    getPerFunctionPasses()->add(createVerifierPass());

  if (CompileOpts.OptimizationLevel > 0) {
    FunctionPassManager *PM = getPerFunctionPasses();
    PM->add(createCFGSimplificationPass());
    if (CompileOpts.OptimizationLevel == 1)
      PM->add(createPromoteMemoryToRegisterPass());
    else
      PM->add(createScalarReplAggregatesPass());
    PM->add(createInstructionCombiningPass());
  }

  // For now we always create per module passes.
  PassManager *PM = getPerModulePasses();
  if (CompileOpts.OptimizationLevel > 0) {
    if (CompileOpts.UnitAtATime)
      PM->add(createRaiseAllocationsPass());      // call %malloc -> malloc inst
    PM->add(createCFGSimplificationPass());       // Clean up disgusting code
    PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas
    if (CompileOpts.UnitAtATime) {
      PM->add(createGlobalOptimizerPass());       // Optimize out global vars
      PM->add(createGlobalDCEPass());             // Remove unused fns and globs
      PM->add(createIPConstantPropagationPass()); // IP Constant Propagation
      PM->add(createDeadArgEliminationPass());    // Dead argument elimination
    }
    PM->add(createInstructionCombiningPass());    // Clean up after IPCP & DAE
    PM->add(createCFGSimplificationPass());       // Clean up after IPCP & DAE
    if (CompileOpts.UnitAtATime) {
      PM->add(createPruneEHPass());               // Remove dead EH info
      PM->add(createFunctionAttrsPass());         // Set readonly/readnone attrs
    }
    if (CompileOpts.InlineFunctions)
      PM->add(createFunctionInliningPass());      // Inline small functions
    else
      PM->add(createAlwaysInlinerPass());         // Respect always_inline
    if (CompileOpts.OptimizationLevel > 2)
      PM->add(createArgumentPromotionPass());     // Scalarize uninlined fn args
    if (CompileOpts.SimplifyLibCalls)
      PM->add(createSimplifyLibCallsPass());      // Library Call Optimizations
    PM->add(createInstructionCombiningPass());    // Cleanup for scalarrepl.
    PM->add(createJumpThreadingPass());           // Thread jumps.
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createScalarReplAggregatesPass());    // Break up aggregate allocas
    PM->add(createInstructionCombiningPass());    // Combine silly seq's
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createTailCallEliminationPass());     // Eliminate tail calls
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createReassociatePass());             // Reassociate expressions
    PM->add(createLoopRotatePass());              // Rotate Loop
    PM->add(createLICMPass());                    // Hoist loop invariants
    PM->add(createLoopUnswitchPass(CompileOpts.OptimizeSize ? true : false));
//    PM->add(createLoopIndexSplitPass());          // Split loop index
    PM->add(createInstructionCombiningPass());
    PM->add(createIndVarSimplifyPass());          // Canonicalize indvars
    PM->add(createLoopDeletionPass());            // Delete dead loops
    if (CompileOpts.UnrollLoops)
      PM->add(createLoopUnrollPass());            // Unroll small loops
    PM->add(createInstructionCombiningPass());    // Clean up after the unroller
    PM->add(createGVNPass());                     // Remove redundancies
    PM->add(createMemCpyOptPass());               // Remove memcpy / form memset
    PM->add(createSCCPPass());                    // Constant prop with SCCP

    // Run instcombine after redundancy elimination to exploit opportunities
    // opened up by them.
    PM->add(createInstructionCombiningPass());
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createDeadStoreEliminationPass());    // Delete dead stores
    PM->add(createAggressiveDCEPass());           // Delete dead instructions
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs

    if (CompileOpts.UnitAtATime) {
      PM->add(createStripDeadPrototypesPass());   // Get rid of dead prototypes
      PM->add(createDeadTypeEliminationPass());   // Eliminate dead types
    }

    if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
      PM->add(createConstantMergePass());         // Merge dup global constants
  } else {
    PM->add(createAlwaysInlinerPass());
  }
}

/// EmitAssembly - Handle interaction with LLVM backend to generate
/// actual machine code.
void BackendConsumer::EmitAssembly() {
  // Silently ignore if we weren't initialized for some reason.
  if (!TheModule || !TheTargetData)
    return;

  // Make sure IR generation is happy with the module. This is
  // released by the module provider.
  Module *M = Gen->ReleaseModule();
  if (!M) {
    // The module has been released by IR gen on failures, do not
    // double free.
    ModuleProvider->releaseModule();
    TheModule = 0;
    return;
  }

  assert(TheModule == M && "Unexpected module change during IR generation");

  CreatePasses();

  std::string Error;
  if (!AddEmitPasses(Error)) {
    // FIXME: Don't fail this way.
    llvm::cerr << "ERROR: " << Error << "\n";
    ::exit(1);
  }

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PerFunctionPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses)
    PerModulePasses->run(*M);

  if (CodeGenPasses) {
    CodeGenPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        CodeGenPasses->run(*I);
    CodeGenPasses->doFinalization();
  }
}

ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
                                          Diagnostic &Diags,
                                          const LangOptions &Features,
                                          const CompileOptions &CompileOpts,
                                          const std::string& InFile,
                                          const std::string& OutFile,
                                          bool GenerateDebugInfo) {
  // FIXME: If optimizing, disable all debug info generation.  The LLVM
  // optimizer and backend is not ready to handle it when optimizations
  // are enabled.
  if (CompileOpts.OptimizationLevel > 0)
    GenerateDebugInfo = false;

  return new BackendConsumer(Action, Diags, Features, CompileOpts,
                             InFile, OutFile, GenerateDebugInfo);
}
<|endoftext|>


<commit_before>// MathLib.cpp
// This file is part of the EScript programming language.
// See copyright notice in EScript.h
// ------------------------------------------------------
#include "MathLib.h"
#include <cmath>

#include "ext/Rand.h"
#include "../EScript/EScript.h"

namespace EScript{
namespace MathLib{

// ---------------------------------------------------------

//! EWrapper for Rand-Class
class E_RandNumGenerator : public ReferenceObject<Rand> {
	ES_PROVIDES_TYPE_NAME(RandNumGenerator);
public:
	//! (static)
	static Type * getTypeObject() {
		static Type * typeObject=new Type(Object::getTypeObject());
		return typeObject;
	}
	static void init(EScript::Namespace & globals);

	//! (ctor)
	E_RandNumGenerator(uint32_t seed=0):
			ReferenceObject<Rand>(seed,getTypeObject()){}

	//! (dtor)
	virtual ~E_RandNumGenerator(){}
};

// ---------------------------------------------------------

//! (static) MathLib init
void init(EScript::Namespace * globals) {
	Namespace * lib=new Namespace();
	declareConstant(globals,"Math",lib);

	declareConstant(lib,"PI",Number::create(M_PI));
	declareConstant(lib,"PI_2",Number::create(M_PI_2));
//
//	/*!	[ESF] number Math.rand(max,[seed])
//		based on // http://www.cs.wm.edu/~va/software/park/	*/
//	ES_FUNCTION_DECLARE(lib,"rand",1,2,{
//		static long seed=1;
//		if (parameter.count()>1)
//			seed=static_cast<unsigned int>(parameter[1].toInt());
//		const long Q = 2147483647 / 48271;
//		const long R = 2147483647 % 48271;
//		long t = 48271 * (seed % Q) - R * (seed / Q);
//		if (t > 0)
//			seed = t;
//		else
//			seed = t + 2147483647;
//		return Number::create( seed%(static_cast<unsigned int>(parameter[0].toInt()+1)));
//	})

	//! Number Math.atan2(a,b)
	ESF_DECLARE(lib, "atan2", 2, 2,
				Number::create(std::atan2(parameter[0].toDouble(), parameter[1].toDouble())))

	// init E_RandNumGenerator
	E_RandNumGenerator::init(*lib);

	// init global E_RandNumGenerator-Object
	declareConstant(globals,"Rand",new E_RandNumGenerator);

	// ------
}

// ---------------------------------------------------------------

//! (static) init members for E_RandNumGenerator
void E_RandNumGenerator::init(EScript::Namespace & lib) {

	// E_Rand ---|> [Object]
	Type * typeObject=getTypeObject();
	declareConstant(&lib,getClassName(),typeObject);

	//! [ESF] new RandNumGenerator( [seed] )
	ESF_DECLARE(typeObject,"_constructor",0,1,(
			new E_RandNumGenerator(parameter[0].toInt(0))))

	//! [ESF] [0,1] RandNumGenerator.bernoulli(p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"bernoulli",1,1,(
			Number::create( self->ref().bernoulli(parameter[0].toDouble()))))

	//! [ESF] int RandNumGenerator.binomial(n,p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"binomial",2,2,
				Number::create( self->ref().binomial(parameter[0].toInt(),parameter[1].toDouble())))

	//! [ESF] float RandNumGenerator.chisquare(n)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"chisquare",1,1,
				Number::create(self->ref().chisquare(parameter[0].toInt())))

	//! [ESF] int RandNumGenerator.equilikely(a,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"equilikely",2,2,
				Number::create(self->ref().equilikely(parameter[0].toInt(),parameter[1].toInt())))

	//! [ESF] float RandNumGenerator.erlang(n,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"erlang",2,2,
				Number::create( self->ref().erlang(parameter[0].toInt(),parameter[1].toDouble())))

	//! [ESF] float RandNumGenerator.exponential(m)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"exponential",1,1,
				Number::create(self->ref().exponential(parameter[0].toDouble())))

	//! [ESF] int RandNumGenerator.geometric(p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"geometric",1,1,
				Number::create( self->ref().geometric(parameter[0].toDouble())))

	//! [ESF] float RandNumGenerator.lognormal(a,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"lognormal",2,2,
				Number::create( self->ref().lognormal(parameter[0].toDouble(),parameter[1].toDouble())))

	//! [ESF] float RandNumGenerator.normal(m,s)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"normal",2,2,
				Number::create( self->ref().normal(parameter[0].toDouble(),parameter[1].toDouble())))

	//! [ESF] int RandNumGenerator.pascal(n,p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"pascal",2,2,
				Number::create(self->ref().pascal(parameter[0].toInt(),parameter[1].toDouble())))

	//! [ESF] int RandNumGenerator.poisson(m)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"poisson",1,1,
				Number::create(self->ref().poisson(parameter[0].toDouble())))

	//! [ESF] float RandNumGenerator.random()      [0.0 ... 1.0]
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"random",0,0,
				Number::create(self->ref().random()))

	//! [ESF]float RandNumGenerator.student(n)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"student",1,1,
				Number::create(self->ref().student(parameter[0].toInt())))

	//! [ESF] float RandNumGenerator.uniform(a,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"uniform",2,2,
				Number::create( self->ref().uniform(parameter[0].toDouble(),parameter[1].toDouble())))

}
// ---------------------------------------------------------------

}
}
<commit_msg>Remove extra ;<commit_after>// MathLib.cpp
// This file is part of the EScript programming language.
// See copyright notice in EScript.h
// ------------------------------------------------------
#include "MathLib.h"
#include <cmath>

#include "ext/Rand.h"
#include "../EScript/EScript.h"

namespace EScript{
namespace MathLib{

// ---------------------------------------------------------

//! EWrapper for Rand-Class
class E_RandNumGenerator : public ReferenceObject<Rand> {
	ES_PROVIDES_TYPE_NAME(RandNumGenerator)
public:
	//! (static)
	static Type * getTypeObject() {
		static Type * typeObject=new Type(Object::getTypeObject());
		return typeObject;
	}
	static void init(EScript::Namespace & globals);

	//! (ctor)
	E_RandNumGenerator(uint32_t seed=0):
			ReferenceObject<Rand>(seed,getTypeObject()){}

	//! (dtor)
	virtual ~E_RandNumGenerator(){}
};

// ---------------------------------------------------------

//! (static) MathLib init
void init(EScript::Namespace * globals) {
	Namespace * lib=new Namespace();
	declareConstant(globals,"Math",lib);

	declareConstant(lib,"PI",Number::create(M_PI));
	declareConstant(lib,"PI_2",Number::create(M_PI_2));
//
//	/*!	[ESF] number Math.rand(max,[seed])
//		based on // http://www.cs.wm.edu/~va/software/park/	*/
//	ES_FUNCTION_DECLARE(lib,"rand",1,2,{
//		static long seed=1;
//		if (parameter.count()>1)
//			seed=static_cast<unsigned int>(parameter[1].toInt());
//		const long Q = 2147483647 / 48271;
//		const long R = 2147483647 % 48271;
//		long t = 48271 * (seed % Q) - R * (seed / Q);
//		if (t > 0)
//			seed = t;
//		else
//			seed = t + 2147483647;
//		return Number::create( seed%(static_cast<unsigned int>(parameter[0].toInt()+1)));
//	})

	//! Number Math.atan2(a,b)
	ESF_DECLARE(lib, "atan2", 2, 2,
				Number::create(std::atan2(parameter[0].toDouble(), parameter[1].toDouble())))

	// init E_RandNumGenerator
	E_RandNumGenerator::init(*lib);

	// init global E_RandNumGenerator-Object
	declareConstant(globals,"Rand",new E_RandNumGenerator);

	// ------
}

// ---------------------------------------------------------------

//! (static) init members for E_RandNumGenerator
void E_RandNumGenerator::init(EScript::Namespace & lib) {

	// E_Rand ---|> [Object]
	Type * typeObject=getTypeObject();
	declareConstant(&lib,getClassName(),typeObject);

	//! [ESF] new RandNumGenerator( [seed] )
	ESF_DECLARE(typeObject,"_constructor",0,1,(
			new E_RandNumGenerator(parameter[0].toInt(0))))

	//! [ESF] [0,1] RandNumGenerator.bernoulli(p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"bernoulli",1,1,(
			Number::create( self->ref().bernoulli(parameter[0].toDouble()))))

	//! [ESF] int RandNumGenerator.binomial(n,p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"binomial",2,2,
				Number::create( self->ref().binomial(parameter[0].toInt(),parameter[1].toDouble())))

	//! [ESF] float RandNumGenerator.chisquare(n)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"chisquare",1,1,
				Number::create(self->ref().chisquare(parameter[0].toInt())))

	//! [ESF] int RandNumGenerator.equilikely(a,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"equilikely",2,2,
				Number::create(self->ref().equilikely(parameter[0].toInt(),parameter[1].toInt())))

	//! [ESF] float RandNumGenerator.erlang(n,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"erlang",2,2,
				Number::create( self->ref().erlang(parameter[0].toInt(),parameter[1].toDouble())))

	//! [ESF] float RandNumGenerator.exponential(m)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"exponential",1,1,
				Number::create(self->ref().exponential(parameter[0].toDouble())))

	//! [ESF] int RandNumGenerator.geometric(p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"geometric",1,1,
				Number::create( self->ref().geometric(parameter[0].toDouble())))

	//! [ESF] float RandNumGenerator.lognormal(a,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"lognormal",2,2,
				Number::create( self->ref().lognormal(parameter[0].toDouble(),parameter[1].toDouble())))

	//! [ESF] float RandNumGenerator.normal(m,s)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"normal",2,2,
				Number::create( self->ref().normal(parameter[0].toDouble(),parameter[1].toDouble())))

	//! [ESF] int RandNumGenerator.pascal(n,p)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"pascal",2,2,
				Number::create(self->ref().pascal(parameter[0].toInt(),parameter[1].toDouble())))

	//! [ESF] int RandNumGenerator.poisson(m)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"poisson",1,1,
				Number::create(self->ref().poisson(parameter[0].toDouble())))

	//! [ESF] float RandNumGenerator.random()      [0.0 ... 1.0]
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"random",0,0,
				Number::create(self->ref().random()))

	//! [ESF]float RandNumGenerator.student(n)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"student",1,1,
				Number::create(self->ref().student(parameter[0].toInt())))

	//! [ESF] float RandNumGenerator.uniform(a,b)
	ESMF_DECLARE(typeObject,E_RandNumGenerator,"uniform",2,2,
				Number::create( self->ref().uniform(parameter[0].toDouble(),parameter[1].toDouble())))

}
// ---------------------------------------------------------------

}
}
<|endoftext|>