<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: manager.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 19:50:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#if STLPORT_VERSION>=321
#include <cstdarg>
#endif

#include <plugin/impl.hxx>

#ifndef _OSL_MUTEX_HXX
#include <osl/mutex.hxx>
#endif
#ifndef INCLUDED_SVTOOLS_PATHOPTIONS_HXX
#include <svtools/pathoptions.hxx>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
#include <com/sun/star/container/XEnumerationAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATION_HPP_
#include <com/sun/star/container/XEnumeration.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XELEMENTACCESS_HPP_
#include <com/sun/star/container/XElementAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
#include <com/sun/star/container/XIndexAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_LOADER_XIMPLEMENTATIONLOADER_HPP_
#include <com/sun/star/loader/XImplementationLoader.hpp>
#endif
#ifndef _COM_SUN_STAR_LOADER_CANNOTACTIVATEFACTORYEXCEPTION_HPP_
#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
#endif

PluginManager* PluginManager::pManager = NULL;

PluginManager& PluginManager::get()
{
    if( ! pManager )
        pManager = new PluginManager();
    return *pManager;
}

void PluginManager::setServiceFactory( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
{
    PluginManager& rManager = get();
    if( ! rManager.m_xSMgr.is() )
        rManager.m_xSMgr = xFactory;
}

PluginManager::PluginManager()
{
}

PluginManager::~PluginManager()
{
}

const Sequence< ::rtl::OUString >& PluginManager::getAdditionalSearchPaths()
{
    static Sequence< ::rtl::OUString > aPaths;

    if( ! aPaths.getLength() )
    {
        SvtPathOptions aOptions;
        String aPluginPath( aOptions.GetPluginPath() );
        if( aPluginPath.Len() )
        {
            int nPaths = aPluginPath.GetTokenCount( ';' );
            aPaths.realloc( nPaths );
            for( int i = 0; i < nPaths; i++ )
                aPaths.getArray()[i] = aPluginPath.GetToken( i, ';' );
        }
    }

    return aPaths;
}

//==================================================================================================
Reference< XInterface > SAL_CALL PluginManager_CreateInstance( const Reference< ::com::sun::star::lang::XMultiServiceFactory >  & rSMgr ) throw( Exception )
{
    Reference< XInterface >  xService = *new XPluginManager_Impl( rSMgr );
    return xService;
}

// ::com::sun::star::lang::XServiceInfo
::rtl::OUString XPluginManager_Impl::getImplementationName() throw(  )

{
    return getImplementationName_Static();

}

// ::com::sun::star::lang::XServiceInfo
sal_Bool XPluginManager_Impl::supportsService(const ::rtl::OUString& ServiceName) throw(  )
{
    Sequence< ::rtl::OUString > aSNL = getSupportedServiceNames();
    const ::rtl::OUString * pArray = aSNL.getConstArray();
    for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
        if( pArray[i] == ServiceName )
            return sal_True;
    return sal_False;
}

// ::com::sun::star::lang::XServiceInfo
Sequence< ::rtl::OUString > XPluginManager_Impl::getSupportedServiceNames(void) throw(  )
{
    return getSupportedServiceNames_Static();
}

// XPluginManager_Impl
Sequence< ::rtl::OUString > XPluginManager_Impl::getSupportedServiceNames_Static(void) throw(  )
{
    Sequence< ::rtl::OUString > aSNS( 1 );
    aSNS.getArray()[0] = ::rtl::OUString::createFromAscii( "com.sun.star.plugin.PluginManager" );
    return aSNS;
}

XPluginManager_Impl::XPluginManager_Impl( const Reference< ::com::sun::star::lang::XMultiServiceFactory >  & rSMgr )
: m_xSMgr( rSMgr )
{
    PluginManager::setServiceFactory( rSMgr );
}

XPluginManager_Impl::~XPluginManager_Impl()
{
}

XPlugin_Impl* XPluginManager_Impl::getXPluginFromNPP( NPP instance )
{
    ::std::list<XPlugin_Impl*>::iterator iter;
    for( iter = PluginManager::get().getPlugins().begin();
         iter != PluginManager::get().getPlugins().end(); ++iter )
    {
        if( (*iter)->getNPPInstance() == instance )
            return *iter;
    }

    return NULL;
}

XPlugin_Impl* XPluginManager_Impl::getPluginImplementation( const Reference< ::com::sun::star::plugin::XPlugin >& plugin )
{
    ::std::list<XPlugin_Impl*>::iterator iter;
    for( iter = PluginManager::get().getPlugins().begin();
         iter != PluginManager::get().getPlugins().end(); ++iter )
    {
        if( plugin == Reference< ::com::sun::star::plugin::XPlugin >((*iter)) )
            return *iter;
    }

    return NULL;
}

XPlugin_Impl* XPluginManager_Impl::getFirstXPlugin()
{
    if( PluginManager::get().getPlugins().begin() == PluginManager::get().getPlugins().end() )
        return NULL;

    return *PluginManager::get().getPlugins().begin();
}

Reference< ::com::sun::star::plugin::XPlugin > XPluginManager_Impl::createPlugin( const Reference< ::com::sun::star::plugin::XPluginContext >& acontext, INT16 mode, const Sequence< ::rtl::OUString >& argn, const Sequence< ::rtl::OUString >& argv, const ::com::sun::star::plugin::PluginDescription& plugintype)
    throw( RuntimeException,::com::sun::star::plugin::PluginException )
{
    XPlugin_Impl* pImpl = new XPlugin_Impl( m_xSMgr );
    pImpl->setPluginContext( acontext );

    PluginManager::get().getPlugins().push_back( pImpl );

    pImpl->initInstance( plugintype,
                         argn,
                         argv,
                         mode );

    return pImpl;
}

Reference< ::com::sun::star::plugin::XPlugin >  XPluginManager_Impl::createPluginFromURL( const Reference< ::com::sun::star::plugin::XPluginContext > & acontext, sal_Int16 mode, const Sequence< ::rtl::OUString >& argn, const Sequence< ::rtl::OUString >& argv, const Reference< ::com::sun::star::awt::XToolkit > & toolkit, const Reference< ::com::sun::star::awt::XWindowPeer > & parent, const ::rtl::OUString& url ) throw()
{
    XPlugin_Impl* pImpl = new XPlugin_Impl( m_xSMgr );
    Reference< ::com::sun::star::plugin::XPlugin >  xRef = pImpl;

    pImpl->setPluginContext( acontext );

    PluginManager::get().getPlugins().push_back( pImpl );

    pImpl->initInstance( url,
                         argn,
                         argv,
                         mode );

    pImpl->createPeer( toolkit, parent );

    pImpl->provideNewStream( pImpl->getDescription().Mimetype,
                             Reference< com::sun::star::io::XActiveDataSource >(),
                             url,
                             0, 0, (sal_Bool)(url.compareToAscii( "file:", 5  ) == 0) );

    if( ! pImpl->getPluginComm() )
    {
        pImpl->dispose();
        xRef = NULL;
    }

    return xRef;
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.7.186); FILE MERGED 2006/09/01 17:26:35 kaib 1.7.186.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: manager.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 13:07:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#if STLPORT_VERSION>=321
#include <cstdarg>
#endif

#include <plugin/impl.hxx>

#ifndef _OSL_MUTEX_HXX
#include <osl/mutex.hxx>
#endif
#ifndef INCLUDED_SVTOOLS_PATHOPTIONS_HXX
#include <svtools/pathoptions.hxx>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
#include <com/sun/star/container/XEnumerationAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATION_HPP_
#include <com/sun/star/container/XEnumeration.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XELEMENTACCESS_HPP_
#include <com/sun/star/container/XElementAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
#include <com/sun/star/container/XIndexAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_LOADER_XIMPLEMENTATIONLOADER_HPP_
#include <com/sun/star/loader/XImplementationLoader.hpp>
#endif
#ifndef _COM_SUN_STAR_LOADER_CANNOTACTIVATEFACTORYEXCEPTION_HPP_
#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
#endif

PluginManager* PluginManager::pManager = NULL;

PluginManager& PluginManager::get()
{
    if( ! pManager )
        pManager = new PluginManager();
    return *pManager;
}

void PluginManager::setServiceFactory( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
{
    PluginManager& rManager = get();
    if( ! rManager.m_xSMgr.is() )
        rManager.m_xSMgr = xFactory;
}

PluginManager::PluginManager()
{
}

PluginManager::~PluginManager()
{
}

const Sequence< ::rtl::OUString >& PluginManager::getAdditionalSearchPaths()
{
    static Sequence< ::rtl::OUString > aPaths;

    if( ! aPaths.getLength() )
    {
        SvtPathOptions aOptions;
        String aPluginPath( aOptions.GetPluginPath() );
        if( aPluginPath.Len() )
        {
            int nPaths = aPluginPath.GetTokenCount( ';' );
            aPaths.realloc( nPaths );
            for( int i = 0; i < nPaths; i++ )
                aPaths.getArray()[i] = aPluginPath.GetToken( i, ';' );
        }
    }

    return aPaths;
}

//==================================================================================================
Reference< XInterface > SAL_CALL PluginManager_CreateInstance( const Reference< ::com::sun::star::lang::XMultiServiceFactory >  & rSMgr ) throw( Exception )
{
    Reference< XInterface >  xService = *new XPluginManager_Impl( rSMgr );
    return xService;
}

// ::com::sun::star::lang::XServiceInfo
::rtl::OUString XPluginManager_Impl::getImplementationName() throw(  )

{
    return getImplementationName_Static();

}

// ::com::sun::star::lang::XServiceInfo
sal_Bool XPluginManager_Impl::supportsService(const ::rtl::OUString& ServiceName) throw(  )
{
    Sequence< ::rtl::OUString > aSNL = getSupportedServiceNames();
    const ::rtl::OUString * pArray = aSNL.getConstArray();
    for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
        if( pArray[i] == ServiceName )
            return sal_True;
    return sal_False;
}

// ::com::sun::star::lang::XServiceInfo
Sequence< ::rtl::OUString > XPluginManager_Impl::getSupportedServiceNames(void) throw(  )
{
    return getSupportedServiceNames_Static();
}

// XPluginManager_Impl
Sequence< ::rtl::OUString > XPluginManager_Impl::getSupportedServiceNames_Static(void) throw(  )
{
    Sequence< ::rtl::OUString > aSNS( 1 );
    aSNS.getArray()[0] = ::rtl::OUString::createFromAscii( "com.sun.star.plugin.PluginManager" );
    return aSNS;
}

XPluginManager_Impl::XPluginManager_Impl( const Reference< ::com::sun::star::lang::XMultiServiceFactory >  & rSMgr )
: m_xSMgr( rSMgr )
{
    PluginManager::setServiceFactory( rSMgr );
}

XPluginManager_Impl::~XPluginManager_Impl()
{
}

XPlugin_Impl* XPluginManager_Impl::getXPluginFromNPP( NPP instance )
{
    ::std::list<XPlugin_Impl*>::iterator iter;
    for( iter = PluginManager::get().getPlugins().begin();
         iter != PluginManager::get().getPlugins().end(); ++iter )
    {
        if( (*iter)->getNPPInstance() == instance )
            return *iter;
    }

    return NULL;
}

XPlugin_Impl* XPluginManager_Impl::getPluginImplementation( const Reference< ::com::sun::star::plugin::XPlugin >& plugin )
{
    ::std::list<XPlugin_Impl*>::iterator iter;
    for( iter = PluginManager::get().getPlugins().begin();
         iter != PluginManager::get().getPlugins().end(); ++iter )
    {
        if( plugin == Reference< ::com::sun::star::plugin::XPlugin >((*iter)) )
            return *iter;
    }

    return NULL;
}

XPlugin_Impl* XPluginManager_Impl::getFirstXPlugin()
{
    if( PluginManager::get().getPlugins().begin() == PluginManager::get().getPlugins().end() )
        return NULL;

    return *PluginManager::get().getPlugins().begin();
}

Reference< ::com::sun::star::plugin::XPlugin > XPluginManager_Impl::createPlugin( const Reference< ::com::sun::star::plugin::XPluginContext >& acontext, INT16 mode, const Sequence< ::rtl::OUString >& argn, const Sequence< ::rtl::OUString >& argv, const ::com::sun::star::plugin::PluginDescription& plugintype)
    throw( RuntimeException,::com::sun::star::plugin::PluginException )
{
    XPlugin_Impl* pImpl = new XPlugin_Impl( m_xSMgr );
    pImpl->setPluginContext( acontext );

    PluginManager::get().getPlugins().push_back( pImpl );

    pImpl->initInstance( plugintype,
                         argn,
                         argv,
                         mode );

    return pImpl;
}

Reference< ::com::sun::star::plugin::XPlugin >  XPluginManager_Impl::createPluginFromURL( const Reference< ::com::sun::star::plugin::XPluginContext > & acontext, sal_Int16 mode, const Sequence< ::rtl::OUString >& argn, const Sequence< ::rtl::OUString >& argv, const Reference< ::com::sun::star::awt::XToolkit > & toolkit, const Reference< ::com::sun::star::awt::XWindowPeer > & parent, const ::rtl::OUString& url ) throw()
{
    XPlugin_Impl* pImpl = new XPlugin_Impl( m_xSMgr );
    Reference< ::com::sun::star::plugin::XPlugin >  xRef = pImpl;

    pImpl->setPluginContext( acontext );

    PluginManager::get().getPlugins().push_back( pImpl );

    pImpl->initInstance( url,
                         argn,
                         argv,
                         mode );

    pImpl->createPeer( toolkit, parent );

    pImpl->provideNewStream( pImpl->getDescription().Mimetype,
                             Reference< com::sun::star::io::XActiveDataSource >(),
                             url,
                             0, 0, (sal_Bool)(url.compareToAscii( "file:", 5  ) == 0) );

    if( ! pImpl->getPluginComm() )
    {
        pImpl->dispose();
        xRef = NULL;
    }

    return xRef;
}

<|endoftext|>


<commit_before>/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/

//------------------------------------------------------------------------------
// Implementation of the AliPerformanceTask class. It checks reconstruction performance
// for the reconstructed vs MC particle tracks under several conditions. For real data
// the control QA histograms are filled.
//
// The comparison output objects deriving from AliPerformanceObject
// (e.g. AliPerformanceRes, AliPerformanceEff, AliPerformanceDEdx, AliPerformanceDCA ...)
// are stored in the output file (details in description of these classes).
//
// Author: J.Otwinowski 01/04/2009
// Changes by M.Knichel 15/10/2010
//------------------------------------------------------------------------------

#include "iostream"

#include "TChain.h"
#include "TTree.h"
#include "TH1F.h"
#include "TCanvas.h"
#include "TList.h"
#include "TFile.h"
#include "TSystem.h"

#include "AliAnalysisTask.h"
#include "AliAnalysisManager.h"
#include "AliESDEvent.h"
#include "AliESDfriend.h"
#include "AliMCEvent.h"
#include "AliESDInputHandler.h"
#include "AliMCEventHandler.h"
#include "AliESDVertex.h"
#include "AliMagF.h"
#include "AliTracker.h"
#include "AliGeomManager.h"

#include "AliMCInfo.h"
#include "AliESDRecInfo.h"
#include "AliMCInfoCuts.h"
#include "AliRecInfoCuts.h"
#include "AliComparisonObject.h"
#include "AliPerformanceObject.h"
#include "AliTPCPerformanceSummary.h"
#include "AliPerformanceTPC.h"
#include "AliPerformanceDEdx.h"
#include "AliPerformanceTask.h"

using namespace std;

ClassImp(AliPerformanceTask)

//_____________________________________________________________________________
AliPerformanceTask::AliPerformanceTask()
  : AliAnalysisTaskSE("Performance")
  , fESD(0)
  , fESDfriend(0)
  , fMC(0)
  , fOutput(0)
  , fOutputSummary(0)
  , fPitList(0)
  , fCompList(0)
  , fUseMCInfo(kFALSE)
  , fUseESDfriend(kFALSE)
  , fUseHLT(kFALSE)
{
  // Dummy Constructor
  // should not be used
}

//_____________________________________________________________________________
AliPerformanceTask::AliPerformanceTask(const char *name, const char */*title*/)
  : AliAnalysisTaskSE(name)
  , fESD(0)
  , fESDfriend(0)
  , fMC(0)
  , fOutput(0)
  , fOutputSummary(0)
  , fPitList(0)
  , fCompList(0)
  , fUseMCInfo(kFALSE)
  , fUseESDfriend(kFALSE)
  , fUseHLT(kFALSE)
{
  // Constructor

  // Define input and output slots here
  DefineOutput(1, TList::Class());
  DefineOutput(2, TTree::Class());

  // create the list for comparison objects
  fCompList = new TList;
}

//_____________________________________________________________________________
AliPerformanceTask::~AliPerformanceTask()
{
  if (fOutput)     delete fOutput;    fOutput   = 0;
  if (fOutputSummary) delete fOutputSummary; fOutputSummary = 0;
  if (fCompList)   delete fCompList;  fCompList = 0;
}

//_____________________________________________________________________________
Bool_t AliPerformanceTask::AddPerformanceObject(AliPerformanceObject *pObj)
{
  // add comparison object to the list
  if(pObj == 0) {
    Printf("ERROR: Could not add comparison object");
    return kFALSE;
  }

  // add object to the list
  fCompList->AddLast(pObj);

return kTRUE;
}

//_____________________________________________________________________________
void AliPerformanceTask::UserCreateOutputObjects()
{
  // Create histograms
  // Called once

  // create output list
  fOutput = new TList;
  fOutput->SetOwner();
  fPitList = fOutput->MakeIterator();

  // create output list
  //fOutputSummary = new TTree;

  // add comparison objects to the output
  AliPerformanceObject *pObj=0;
  Int_t count=0;
  TIterator *pitCompList = fCompList->MakeIterator();
  pitCompList->Reset();
  while(( pObj = (AliPerformanceObject *)pitCompList->Next()) != NULL) {
    fOutput->Add(pObj);
    count++;
  }
  Printf("UserCreateOutputObjects(): Number of output comparison objects: %d \n", count);

  PostData(1, fOutput);
  //PostData(2, fOutputSummary);
}

//_____________________________________________________________________________
void AliPerformanceTask::UserExec(Option_t *)
{
  // Main loop
  // Called for each event

  // Decide whether to use HLT or Offline ESD
  if(fUseHLT){

    AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*>
      (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());

    if (!esdH) {
      printf("ERROR: Could not get ESDInputHandler");
      return;
    }
    fESD = esdH->GetHLTEvent();
  }// end if fUseHLT
  else
    fESD = (AliESDEvent*) (InputEvent());

  if(fUseESDfriend)
    {
      fESDfriend = static_cast<AliESDfriend*>(fESD->FindListObject("AliESDfriend"));
      if(!fESDfriend) {
        Printf("ERROR: ESD friends not available");
      }
    }

  if(fUseMCInfo) {
      fMC = MCEvent();
  }

  //
  AliPerformanceObject *pObj=0;

  if (!fESD) {
    Printf("ERROR: ESD event not available");
    return;
  }

  if (fUseMCInfo && !fMC) {
    Printf("ERROR: MC event not available");
    return;
  }

  if(fUseESDfriend)
  {
    if(!fESDfriend) {
    Printf("ERROR: ESD friends not available");
    }
  }

  // Process comparison
  fPitList->Reset();
  while(( pObj = (AliPerformanceObject *)fPitList->Next()) != NULL) {
    pObj->Exec(fMC,fESD,fESDfriend,fUseMCInfo,fUseESDfriend);
  }

  // Post output data.
  PostData(1, fOutput);
}

//_____________________________________________________________________________
void AliPerformanceTask::Terminate(Option_t *)
{
  // Called once at the end

  // check output data
    fOutputSummary = dynamic_cast<TTree*> (GetOutputData(2));
    fOutput = dynamic_cast<TList*> (GetOutputData(1));
    if (!fOutput) {
        Printf("ERROR: AliPerformanceTask::Terminate(): fOutput data not available  ..." );
        return;
   }
    if (fOutputSummary) { delete fOutputSummary; fOutputSummary=0; }
    AliPerformanceObject* pObj=0;
    AliPerformanceTPC*  pTPC = 0;
    AliPerformanceDEdx* pDEdx = 0;
    TIterator* itOut = fOutput->MakeIterator();
    itOut->Reset();
    while(( pObj = dynamic_cast<AliPerformanceObject*>(itOut->Next())) != NULL) {
        if (!  pTPC) {  pTPC = dynamic_cast<AliPerformanceTPC*>(pObj); }
        if (! pDEdx) { pDEdx = dynamic_cast<AliPerformanceDEdx*>(pObj); }
    }
    if (! AliCDBManager::Instance()->GetDefaultStorage()) { AliCDBManager::Instance()->SetDefaultStorage("raw://"); }
    TUUID uuid;
    TString tmpFile = gSystem->TempDirectory() + TString("/TPCQASummary.") + uuid.AsString() + TString(".root");
    AliTPCPerformanceSummary::WriteToFile(pTPC, pDEdx, tmpFile.Data());
    TChain* chain = new TChain("tpcQA");
    chain->Add(tmpFile.Data());
    TTree *tree = chain->CopyTree("1");
    if (chain) { delete chain; chain=0; }
    fOutputSummary = tree;

     // Post output data.
     PostData(2, fOutputSummary);

}

//_____________________________________________________________________________
void AliPerformanceTask::FinishTaskOutput()
{
    // called once at the end of each job (on the workernode)
    //
    // projects THnSparse to TH1,2,3

    fOutput = dynamic_cast<TList*> (GetOutputData(1));
    if (!fOutput) {
        Printf("ERROR: AliPerformanceTask::FinishTaskOutput(): fOutput data not available  ..." );
        return;
   }

      AliPerformanceObject* pObj=0;
      TIterator* itOut = fOutput->MakeIterator();
      itOut->Reset();
      while(( pObj = dynamic_cast<AliPerformanceObject*>(itOut->Next())) != NULL) {
          pObj->SetRunNumber(fCurrentRunNumber);
          pObj->Analyse();
      }

     // Post output data.
     PostData(1, fOutput);
}

//_____________________________________________________________________________
Bool_t AliPerformanceTask::Notify()
{
  static Int_t count = 0;
  count++;
  Printf("Processing %d. file", count);

  return kTRUE;
}
<commit_msg>missing include<commit_after>/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/

//------------------------------------------------------------------------------
// Implementation of the AliPerformanceTask class. It checks reconstruction performance
// for the reconstructed vs MC particle tracks under several conditions. For real data
// the control QA histograms are filled.
//
// The comparison output objects deriving from AliPerformanceObject
// (e.g. AliPerformanceRes, AliPerformanceEff, AliPerformanceDEdx, AliPerformanceDCA ...)
// are stored in the output file (details in description of these classes).
//
// Author: J.Otwinowski 01/04/2009
// Changes by M.Knichel 15/10/2010
//------------------------------------------------------------------------------

#include "iostream"

#include "TChain.h"
#include "TTree.h"
#include "TH1F.h"
#include "TCanvas.h"
#include "TList.h"
#include "TFile.h"
#include "TSystem.h"

#include "AliAnalysisTask.h"
#include "AliAnalysisManager.h"
#include "AliESDEvent.h"
#include "AliESDfriend.h"
#include "AliMCEvent.h"
#include "AliESDInputHandler.h"
#include "AliMCEventHandler.h"
#include "AliESDVertex.h"
#include "AliMagF.h"
#include "AliTracker.h"
#include "AliGeomManager.h"
#include "AliCDBManager.h"

#include "AliMCInfo.h"
#include "AliESDRecInfo.h"
#include "AliMCInfoCuts.h"
#include "AliRecInfoCuts.h"
#include "AliComparisonObject.h"
#include "AliPerformanceObject.h"
#include "AliTPCPerformanceSummary.h"
#include "AliPerformanceTPC.h"
#include "AliPerformanceDEdx.h"
#include "AliPerformanceTask.h"

using namespace std;

ClassImp(AliPerformanceTask)

//_____________________________________________________________________________
AliPerformanceTask::AliPerformanceTask()
  : AliAnalysisTaskSE("Performance")
  , fESD(0)
  , fESDfriend(0)
  , fMC(0)
  , fOutput(0)
  , fOutputSummary(0)
  , fPitList(0)
  , fCompList(0)
  , fUseMCInfo(kFALSE)
  , fUseESDfriend(kFALSE)
  , fUseHLT(kFALSE)
{
  // Dummy Constructor
  // should not be used
}

//_____________________________________________________________________________
AliPerformanceTask::AliPerformanceTask(const char *name, const char */*title*/)
  : AliAnalysisTaskSE(name)
  , fESD(0)
  , fESDfriend(0)
  , fMC(0)
  , fOutput(0)
  , fOutputSummary(0)
  , fPitList(0)
  , fCompList(0)
  , fUseMCInfo(kFALSE)
  , fUseESDfriend(kFALSE)
  , fUseHLT(kFALSE)
{
  // Constructor

  // Define input and output slots here
  DefineOutput(1, TList::Class());
  DefineOutput(2, TTree::Class());

  // create the list for comparison objects
  fCompList = new TList;
}

//_____________________________________________________________________________
AliPerformanceTask::~AliPerformanceTask()
{
  if (fOutput)     delete fOutput;    fOutput   = 0;
  if (fOutputSummary) delete fOutputSummary; fOutputSummary = 0;
  if (fCompList)   delete fCompList;  fCompList = 0;
}

//_____________________________________________________________________________
Bool_t AliPerformanceTask::AddPerformanceObject(AliPerformanceObject *pObj)
{
  // add comparison object to the list
  if(pObj == 0) {
    Printf("ERROR: Could not add comparison object");
    return kFALSE;
  }

  // add object to the list
  fCompList->AddLast(pObj);

return kTRUE;
}

//_____________________________________________________________________________
void AliPerformanceTask::UserCreateOutputObjects()
{
  // Create histograms
  // Called once

  // create output list
  fOutput = new TList;
  fOutput->SetOwner();
  fPitList = fOutput->MakeIterator();

  // create output list
  //fOutputSummary = new TTree;

  // add comparison objects to the output
  AliPerformanceObject *pObj=0;
  Int_t count=0;
  TIterator *pitCompList = fCompList->MakeIterator();
  pitCompList->Reset();
  while(( pObj = (AliPerformanceObject *)pitCompList->Next()) != NULL) {
    fOutput->Add(pObj);
    count++;
  }
  Printf("UserCreateOutputObjects(): Number of output comparison objects: %d \n", count);

  PostData(1, fOutput);
  //PostData(2, fOutputSummary);
}

//_____________________________________________________________________________
void AliPerformanceTask::UserExec(Option_t *)
{
  // Main loop
  // Called for each event

  // Decide whether to use HLT or Offline ESD
  if(fUseHLT){

    AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*>
      (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());

    if (!esdH) {
      printf("ERROR: Could not get ESDInputHandler");
      return;
    }
    fESD = esdH->GetHLTEvent();
  }// end if fUseHLT
  else
    fESD = (AliESDEvent*) (InputEvent());

  if(fUseESDfriend)
    {
      fESDfriend = static_cast<AliESDfriend*>(fESD->FindListObject("AliESDfriend"));
      if(!fESDfriend) {
        Printf("ERROR: ESD friends not available");
      }
    }

  if(fUseMCInfo) {
      fMC = MCEvent();
  }

  //
  AliPerformanceObject *pObj=0;

  if (!fESD) {
    Printf("ERROR: ESD event not available");
    return;
  }

  if (fUseMCInfo && !fMC) {
    Printf("ERROR: MC event not available");
    return;
  }

  if(fUseESDfriend)
  {
    if(!fESDfriend) {
    Printf("ERROR: ESD friends not available");
    }
  }

  // Process comparison
  fPitList->Reset();
  while(( pObj = (AliPerformanceObject *)fPitList->Next()) != NULL) {
    pObj->Exec(fMC,fESD,fESDfriend,fUseMCInfo,fUseESDfriend);
  }

  // Post output data.
  PostData(1, fOutput);
}

//_____________________________________________________________________________
void AliPerformanceTask::Terminate(Option_t *)
{
  // Called once at the end

  // check output data
    fOutputSummary = dynamic_cast<TTree*> (GetOutputData(2));
    fOutput = dynamic_cast<TList*> (GetOutputData(1));
    if (!fOutput) {
        Printf("ERROR: AliPerformanceTask::Terminate(): fOutput data not available  ..." );
        return;
   }
    if (fOutputSummary) { delete fOutputSummary; fOutputSummary=0; }
    AliPerformanceObject* pObj=0;
    AliPerformanceTPC*  pTPC = 0;
    AliPerformanceDEdx* pDEdx = 0;
    TIterator* itOut = fOutput->MakeIterator();
    itOut->Reset();
    while(( pObj = dynamic_cast<AliPerformanceObject*>(itOut->Next())) != NULL) {
        if (!  pTPC) {  pTPC = dynamic_cast<AliPerformanceTPC*>(pObj); }
        if (! pDEdx) { pDEdx = dynamic_cast<AliPerformanceDEdx*>(pObj); }
    }
    if (! AliCDBManager::Instance()->GetDefaultStorage()) { AliCDBManager::Instance()->SetDefaultStorage("raw://"); }
    TUUID uuid;
    TString tmpFile = gSystem->TempDirectory() + TString("/TPCQASummary.") + uuid.AsString() + TString(".root");
    AliTPCPerformanceSummary::WriteToFile(pTPC, pDEdx, tmpFile.Data());
    TChain* chain = new TChain("tpcQA");
    chain->Add(tmpFile.Data());
    TTree *tree = chain->CopyTree("1");
    if (chain) { delete chain; chain=0; }
    fOutputSummary = tree;

     // Post output data.
     PostData(2, fOutputSummary);

}

//_____________________________________________________________________________
void AliPerformanceTask::FinishTaskOutput()
{
    // called once at the end of each job (on the workernode)
    //
    // projects THnSparse to TH1,2,3

    fOutput = dynamic_cast<TList*> (GetOutputData(1));
    if (!fOutput) {
        Printf("ERROR: AliPerformanceTask::FinishTaskOutput(): fOutput data not available  ..." );
        return;
   }

      AliPerformanceObject* pObj=0;
      TIterator* itOut = fOutput->MakeIterator();
      itOut->Reset();
      while(( pObj = dynamic_cast<AliPerformanceObject*>(itOut->Next())) != NULL) {
          pObj->SetRunNumber(fCurrentRunNumber);
          pObj->Analyse();
      }

     // Post output data.
     PostData(1, fOutput);
}

//_____________________________________________________________________________
Bool_t AliPerformanceTask::Notify()
{
  static Int_t count = 0;
  count++;
  Printf("Processing %d. file", count);

  return kTRUE;
}
<|endoftext|>


<commit_before>//===-- JIT.cpp - LLVM Just in Time Compiler ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool implements a just-in-time compiler for LLVM, allowing direct
// execution of LLVM bytecode in an efficient manner.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/ModuleProvider.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetJITInfo.h"
#include <iostream>
using namespace llvm;

static struct RegisterJIT {
  RegisterJIT() { JIT::Register(); }
} JITRegistrator;

namespace llvm {
  void LinkInJIT() {
  }
}

JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji)
  : ExecutionEngine(MP), TM(tm), TJI(tji), state(MP) {
  setTargetData(TM.getTargetData());

  // Initialize MCE
  MCE = createEmitter(*this);

  // Add target data
  MutexGuard locked(lock);
  FunctionPassManager& PM = state.getPM(locked);
  PM.add(new TargetData(*TM.getTargetData()));

  // Compile LLVM Code down to machine code in the intermediate representation
  TJI.addPassesToJITCompile(PM);

  // Turn the machine code intermediate representation into bytes in memory that
  // may be executed.
  if (TM.addPassesToEmitMachineCode(PM, *MCE)) {
    std::cerr << "Target '" << TM.getName()
              << "' doesn't support machine code emission!\n";
    abort();
  }
}

JIT::~JIT() {
  delete MCE;
  delete &TM;
}

/// run - Start execution with the specified function and arguments.
///
GenericValue JIT::runFunction(Function *F,
                              const std::vector<GenericValue> &ArgValues) {
  assert(F && "Function *F was null at entry to run()");

  void *FPtr = getPointerToFunction(F);
  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
  const FunctionType *FTy = F->getFunctionType();
  const Type *RetTy = FTy->getReturnType();

  assert((FTy->getNumParams() <= ArgValues.size() || FTy->isVarArg()) &&
         "Too many arguments passed into function!");
  assert(FTy->getNumParams() == ArgValues.size() &&
         "This doesn't support passing arguments through varargs (yet)!");

  // Handle some common cases first.  These cases correspond to common `main'
  // prototypes.
  if (RetTy == Type::IntTy || RetTy == Type::UIntTy || RetTy == Type::VoidTy) {
    switch (ArgValues.size()) {
    case 3:
      if ((FTy->getParamType(0) == Type::IntTy ||
           FTy->getParamType(0) == Type::UIntTy) &&
          isa<PointerType>(FTy->getParamType(1)) &&
          isa<PointerType>(FTy->getParamType(2))) {
        int (*PF)(int, char **, const char **) =
          (int(*)(int, char **, const char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = PF(ArgValues[0].IntVal, (char **)GVTOP(ArgValues[1]),
                       (const char **)GVTOP(ArgValues[2]));
        return rv;
      }
      break;
    case 2:
      if ((FTy->getParamType(0) == Type::IntTy ||
           FTy->getParamType(0) == Type::UIntTy) &&
          isa<PointerType>(FTy->getParamType(1))) {
        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = PF(ArgValues[0].IntVal, (char **)GVTOP(ArgValues[1]));
        return rv;
      }
      break;
    case 1:
      if (FTy->getNumParams() == 1 &&
          (FTy->getParamType(0) == Type::IntTy ||
           FTy->getParamType(0) == Type::UIntTy)) {
        GenericValue rv;
        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
        rv.IntVal = PF(ArgValues[0].IntVal);
        return rv;
      }
      break;
    }
  }

  // Handle cases where no arguments are passed first.
  if (ArgValues.empty()) {
    GenericValue rv;
    switch (RetTy->getTypeID()) {
    default: assert(0 && "Unknown return type for function call!");
    case Type::BoolTyID:
      rv.BoolVal = ((bool(*)())(intptr_t)FPtr)();
      return rv;
    case Type::SByteTyID:
    case Type::UByteTyID:
      rv.SByteVal = ((char(*)())(intptr_t)FPtr)();
      return rv;
    case Type::ShortTyID:
    case Type::UShortTyID:
      rv.ShortVal = ((short(*)())(intptr_t)FPtr)();
      return rv;
    case Type::VoidTyID:
    case Type::IntTyID:
    case Type::UIntTyID:
      rv.IntVal = ((int(*)())(intptr_t)FPtr)();
      return rv;
    case Type::LongTyID:
    case Type::ULongTyID:
      rv.LongVal = ((int64_t(*)())(intptr_t)FPtr)();
      return rv;
    case Type::FloatTyID:
      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
      return rv;
    case Type::DoubleTyID:
      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
      return rv;
    case Type::PointerTyID:
      return PTOGV(((void*(*)())(intptr_t)FPtr)());
    }
  }

  // Okay, this is not one of our quick and easy cases.  Because we don't have a
  // full FFI, we have to codegen a nullary stub function that just calls the
  // function we are interested in, passing in constants for all of the
  // arguments.  Make this function and return.

  // First, create the function.
  FunctionType *STy=FunctionType::get(RetTy, std::vector<const Type*>(), false);
  Function *Stub = new Function(STy, Function::InternalLinkage, "",
                                F->getParent());

  // Insert a basic block.
  BasicBlock *StubBB = new BasicBlock("", Stub);

  // Convert all of the GenericValue arguments over to constants.  Note that we
  // currently don't support varargs.
  std::vector<Value*> Args;
  for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) {
    Constant *C = 0;
    const Type *ArgTy = FTy->getParamType(i);
    const GenericValue &AV = ArgValues[i];
    switch (ArgTy->getTypeID()) {
    default: assert(0 && "Unknown argument type for function call!");
    case Type::BoolTyID:   C = ConstantBool::get(AV.BoolVal); break;
    case Type::SByteTyID:  C = ConstantSInt::get(ArgTy, AV.SByteVal);  break;
    case Type::UByteTyID:  C = ConstantUInt::get(ArgTy, AV.UByteVal);  break;
    case Type::ShortTyID:  C = ConstantSInt::get(ArgTy, AV.ShortVal);  break;
    case Type::UShortTyID: C = ConstantUInt::get(ArgTy, AV.UShortVal); break;
    case Type::IntTyID:    C = ConstantSInt::get(ArgTy, AV.IntVal);    break;
    case Type::UIntTyID:   C = ConstantUInt::get(ArgTy, AV.UIntVal);   break;
    case Type::LongTyID:   C = ConstantSInt::get(ArgTy, AV.LongVal);   break;
    case Type::ULongTyID:  C = ConstantUInt::get(ArgTy, AV.ULongVal);  break;
    case Type::FloatTyID:  C = ConstantFP  ::get(ArgTy, AV.FloatVal);  break;
    case Type::DoubleTyID: C = ConstantFP  ::get(ArgTy, AV.DoubleVal); break;
    case Type::PointerTyID:
      void *ArgPtr = GVTOP(AV);
      if (sizeof(void*) == 4) {
        C = ConstantSInt::get(Type::IntTy, (int)(intptr_t)ArgPtr);
      } else {
        C = ConstantSInt::get(Type::LongTy, (intptr_t)ArgPtr);
      }
      C = ConstantExpr::getCast(C, ArgTy);  // Cast the integer to pointer
      break;
    }
    Args.push_back(C);
  }

  CallInst *TheCall = new CallInst(F, Args, "", StubBB);
  TheCall->setTailCall();
  if (TheCall->getType() != Type::VoidTy)
    new ReturnInst(TheCall, StubBB);             // Return result of the call.
  else
    new ReturnInst(StubBB);                      // Just return void.

  // Finally, return the value returned by our nullary stub function.
  return runFunction(Stub, std::vector<GenericValue>());
}

/// runJITOnFunction - Run the FunctionPassManager full of
/// just-in-time compilation passes on F, hopefully filling in
/// GlobalAddress[F] with the address of F's machine code.
///
void JIT::runJITOnFunction(Function *F) {
  static bool isAlreadyCodeGenerating = false;
  assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!");

  MutexGuard locked(lock);

  // JIT the function
  isAlreadyCodeGenerating = true;
  state.getPM(locked).run(*F);
  isAlreadyCodeGenerating = false;

  // If the function referred to a global variable that had not yet been
  // emitted, it allocates memory for the global, but doesn't emit it yet.  Emit
  // all of these globals now.
  while (!state.getPendingGlobals(locked).empty()) {
    const GlobalVariable *GV = state.getPendingGlobals(locked).back();
    state.getPendingGlobals(locked).pop_back();
    EmitGlobalVariable(GV);
  }
}

/// getPointerToFunction - This method is used to get the address of the
/// specified function, compiling it if neccesary.
///
void *JIT::getPointerToFunction(Function *F) {
  MutexGuard locked(lock);

  if (void *Addr = getPointerToGlobalIfAvailable(F))
    return Addr;   // Check if function already code gen'd

  // Make sure we read in the function if it exists in this Module
  if (F->hasNotBeenReadFromBytecode()) {
    std::string ErrorMsg;
    if (MP->materializeFunction(F, &ErrorMsg)) {
      std::cerr << "Error reading function '" << F->getName()
                << "' from bytecode file: " << ErrorMsg << "\n";
      abort();
    }
  }

  if (F->isExternal()) {
    void *Addr = getPointerToNamedFunction(F->getName());
    addGlobalMapping(F, Addr);
    return Addr;
  }

  runJITOnFunction(F);

  void *Addr = getPointerToGlobalIfAvailable(F);
  assert(Addr && "Code generation didn't add function to GlobalAddress table!");
  return Addr;
}

/// getOrEmitGlobalVariable - Return the address of the specified global
/// variable, possibly emitting it to memory if needed.  This is used by the
/// Emitter.
void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
  MutexGuard locked(lock);

  void *Ptr = getPointerToGlobalIfAvailable(GV);
  if (Ptr) return Ptr;

  // If the global is external, just remember the address.
  if (GV->isExternal()) {
    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName().c_str());
    if (Ptr == 0) {
      std::cerr << "Could not resolve external global address: "
                << GV->getName() << "\n";
      abort();
    }
  } else {
    // If the global hasn't been emitted to memory yet, allocate space.  We will
    // actually initialize the global after current function has finished
    // compilation.
    const Type *GlobalType = GV->getType()->getElementType();
    size_t S = getTargetData()->getTypeSize(GlobalType);
    size_t A = getTargetData()->getTypeAlignment(GlobalType);
    if (A <= 8) {
      Ptr = malloc(S);
    } else {
      // Allocate S+A bytes of memory, then use an aligned pointer within that
      // space.
      Ptr = malloc(S+A);
      unsigned MisAligned = ((intptr_t)Ptr & (A-1));
      Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0);
    }
    state.getPendingGlobals(locked).push_back(GV);
  }
  addGlobalMapping(GV, Ptr);
  return Ptr;
}

/// recompileAndRelinkFunction - This method is used to force a function
/// which has already been compiled, to be compiled again, possibly
/// after it has been modified. Then the entry to the old copy is overwritten
/// with a branch to the new copy. If there was no old copy, this acts
/// just like JIT::getPointerToFunction().
///
void *JIT::recompileAndRelinkFunction(Function *F) {
  void *OldAddr = getPointerToGlobalIfAvailable(F);

  // If it's not already compiled there is no reason to patch it up.
  if (OldAddr == 0) { return getPointerToFunction(F); }

  // Delete the old function mapping.
  addGlobalMapping(F, 0);

  // Recodegen the function
  runJITOnFunction(F);

  // Update state, forward the old function to the new function.
  void *Addr = getPointerToGlobalIfAvailable(F);
  assert(Addr && "Code generation didn't add function to GlobalAddress table!");
  TJI.replaceMachineCodeForFunction(OldAddr, Addr);
  return Addr;
}

<commit_msg>Resolve __dso_handle.<commit_after>//===-- JIT.cpp - LLVM Just in Time Compiler ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool implements a just-in-time compiler for LLVM, allowing direct
// execution of LLVM bytecode in an efficient manner.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/ModuleProvider.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetJITInfo.h"
#include <iostream>
using namespace llvm;

#ifdef __APPLE__
// __dso_handle is resolved by Mac OS X dynamic linker.
extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
#endif

static struct RegisterJIT {
  RegisterJIT() { JIT::Register(); }
} JITRegistrator;

namespace llvm {
  void LinkInJIT() {
  }
}

JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji)
  : ExecutionEngine(MP), TM(tm), TJI(tji), state(MP) {
  setTargetData(TM.getTargetData());

  // Initialize MCE
  MCE = createEmitter(*this);

  // Add target data
  MutexGuard locked(lock);
  FunctionPassManager& PM = state.getPM(locked);
  PM.add(new TargetData(*TM.getTargetData()));

  // Compile LLVM Code down to machine code in the intermediate representation
  TJI.addPassesToJITCompile(PM);

  // Turn the machine code intermediate representation into bytes in memory that
  // may be executed.
  if (TM.addPassesToEmitMachineCode(PM, *MCE)) {
    std::cerr << "Target '" << TM.getName()
              << "' doesn't support machine code emission!\n";
    abort();
  }
}

JIT::~JIT() {
  delete MCE;
  delete &TM;
}

/// run - Start execution with the specified function and arguments.
///
GenericValue JIT::runFunction(Function *F,
                              const std::vector<GenericValue> &ArgValues) {
  assert(F && "Function *F was null at entry to run()");

  void *FPtr = getPointerToFunction(F);
  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
  const FunctionType *FTy = F->getFunctionType();
  const Type *RetTy = FTy->getReturnType();

  assert((FTy->getNumParams() <= ArgValues.size() || FTy->isVarArg()) &&
         "Too many arguments passed into function!");
  assert(FTy->getNumParams() == ArgValues.size() &&
         "This doesn't support passing arguments through varargs (yet)!");

  // Handle some common cases first.  These cases correspond to common `main'
  // prototypes.
  if (RetTy == Type::IntTy || RetTy == Type::UIntTy || RetTy == Type::VoidTy) {
    switch (ArgValues.size()) {
    case 3:
      if ((FTy->getParamType(0) == Type::IntTy ||
           FTy->getParamType(0) == Type::UIntTy) &&
          isa<PointerType>(FTy->getParamType(1)) &&
          isa<PointerType>(FTy->getParamType(2))) {
        int (*PF)(int, char **, const char **) =
          (int(*)(int, char **, const char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = PF(ArgValues[0].IntVal, (char **)GVTOP(ArgValues[1]),
                       (const char **)GVTOP(ArgValues[2]));
        return rv;
      }
      break;
    case 2:
      if ((FTy->getParamType(0) == Type::IntTy ||
           FTy->getParamType(0) == Type::UIntTy) &&
          isa<PointerType>(FTy->getParamType(1))) {
        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = PF(ArgValues[0].IntVal, (char **)GVTOP(ArgValues[1]));
        return rv;
      }
      break;
    case 1:
      if (FTy->getNumParams() == 1 &&
          (FTy->getParamType(0) == Type::IntTy ||
           FTy->getParamType(0) == Type::UIntTy)) {
        GenericValue rv;
        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
        rv.IntVal = PF(ArgValues[0].IntVal);
        return rv;
      }
      break;
    }
  }

  // Handle cases where no arguments are passed first.
  if (ArgValues.empty()) {
    GenericValue rv;
    switch (RetTy->getTypeID()) {
    default: assert(0 && "Unknown return type for function call!");
    case Type::BoolTyID:
      rv.BoolVal = ((bool(*)())(intptr_t)FPtr)();
      return rv;
    case Type::SByteTyID:
    case Type::UByteTyID:
      rv.SByteVal = ((char(*)())(intptr_t)FPtr)();
      return rv;
    case Type::ShortTyID:
    case Type::UShortTyID:
      rv.ShortVal = ((short(*)())(intptr_t)FPtr)();
      return rv;
    case Type::VoidTyID:
    case Type::IntTyID:
    case Type::UIntTyID:
      rv.IntVal = ((int(*)())(intptr_t)FPtr)();
      return rv;
    case Type::LongTyID:
    case Type::ULongTyID:
      rv.LongVal = ((int64_t(*)())(intptr_t)FPtr)();
      return rv;
    case Type::FloatTyID:
      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
      return rv;
    case Type::DoubleTyID:
      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
      return rv;
    case Type::PointerTyID:
      return PTOGV(((void*(*)())(intptr_t)FPtr)());
    }
  }

  // Okay, this is not one of our quick and easy cases.  Because we don't have a
  // full FFI, we have to codegen a nullary stub function that just calls the
  // function we are interested in, passing in constants for all of the
  // arguments.  Make this function and return.

  // First, create the function.
  FunctionType *STy=FunctionType::get(RetTy, std::vector<const Type*>(), false);
  Function *Stub = new Function(STy, Function::InternalLinkage, "",
                                F->getParent());

  // Insert a basic block.
  BasicBlock *StubBB = new BasicBlock("", Stub);

  // Convert all of the GenericValue arguments over to constants.  Note that we
  // currently don't support varargs.
  std::vector<Value*> Args;
  for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) {
    Constant *C = 0;
    const Type *ArgTy = FTy->getParamType(i);
    const GenericValue &AV = ArgValues[i];
    switch (ArgTy->getTypeID()) {
    default: assert(0 && "Unknown argument type for function call!");
    case Type::BoolTyID:   C = ConstantBool::get(AV.BoolVal); break;
    case Type::SByteTyID:  C = ConstantSInt::get(ArgTy, AV.SByteVal);  break;
    case Type::UByteTyID:  C = ConstantUInt::get(ArgTy, AV.UByteVal);  break;
    case Type::ShortTyID:  C = ConstantSInt::get(ArgTy, AV.ShortVal);  break;
    case Type::UShortTyID: C = ConstantUInt::get(ArgTy, AV.UShortVal); break;
    case Type::IntTyID:    C = ConstantSInt::get(ArgTy, AV.IntVal);    break;
    case Type::UIntTyID:   C = ConstantUInt::get(ArgTy, AV.UIntVal);   break;
    case Type::LongTyID:   C = ConstantSInt::get(ArgTy, AV.LongVal);   break;
    case Type::ULongTyID:  C = ConstantUInt::get(ArgTy, AV.ULongVal);  break;
    case Type::FloatTyID:  C = ConstantFP  ::get(ArgTy, AV.FloatVal);  break;
    case Type::DoubleTyID: C = ConstantFP  ::get(ArgTy, AV.DoubleVal); break;
    case Type::PointerTyID:
      void *ArgPtr = GVTOP(AV);
      if (sizeof(void*) == 4) {
        C = ConstantSInt::get(Type::IntTy, (int)(intptr_t)ArgPtr);
      } else {
        C = ConstantSInt::get(Type::LongTy, (intptr_t)ArgPtr);
      }
      C = ConstantExpr::getCast(C, ArgTy);  // Cast the integer to pointer
      break;
    }
    Args.push_back(C);
  }

  CallInst *TheCall = new CallInst(F, Args, "", StubBB);
  TheCall->setTailCall();
  if (TheCall->getType() != Type::VoidTy)
    new ReturnInst(TheCall, StubBB);             // Return result of the call.
  else
    new ReturnInst(StubBB);                      // Just return void.

  // Finally, return the value returned by our nullary stub function.
  return runFunction(Stub, std::vector<GenericValue>());
}

/// runJITOnFunction - Run the FunctionPassManager full of
/// just-in-time compilation passes on F, hopefully filling in
/// GlobalAddress[F] with the address of F's machine code.
///
void JIT::runJITOnFunction(Function *F) {
  static bool isAlreadyCodeGenerating = false;
  assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!");

  MutexGuard locked(lock);

  // JIT the function
  isAlreadyCodeGenerating = true;
  state.getPM(locked).run(*F);
  isAlreadyCodeGenerating = false;

  // If the function referred to a global variable that had not yet been
  // emitted, it allocates memory for the global, but doesn't emit it yet.  Emit
  // all of these globals now.
  while (!state.getPendingGlobals(locked).empty()) {
    const GlobalVariable *GV = state.getPendingGlobals(locked).back();
    state.getPendingGlobals(locked).pop_back();
    EmitGlobalVariable(GV);
  }
}

/// getPointerToFunction - This method is used to get the address of the
/// specified function, compiling it if neccesary.
///
void *JIT::getPointerToFunction(Function *F) {
  MutexGuard locked(lock);

  if (void *Addr = getPointerToGlobalIfAvailable(F))
    return Addr;   // Check if function already code gen'd

  // Make sure we read in the function if it exists in this Module
  if (F->hasNotBeenReadFromBytecode()) {
    std::string ErrorMsg;
    if (MP->materializeFunction(F, &ErrorMsg)) {
      std::cerr << "Error reading function '" << F->getName()
                << "' from bytecode file: " << ErrorMsg << "\n";
      abort();
    }
  }

  if (F->isExternal()) {
    void *Addr = getPointerToNamedFunction(F->getName());
    addGlobalMapping(F, Addr);
    return Addr;
  }

  runJITOnFunction(F);

  void *Addr = getPointerToGlobalIfAvailable(F);
  assert(Addr && "Code generation didn't add function to GlobalAddress table!");
  return Addr;
}

/// getOrEmitGlobalVariable - Return the address of the specified global
/// variable, possibly emitting it to memory if needed.  This is used by the
/// Emitter.
void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
  MutexGuard locked(lock);

  void *Ptr = getPointerToGlobalIfAvailable(GV);
  if (Ptr) return Ptr;

  // If the global is external, just remember the address.
  if (GV->isExternal()) {
    // __dso_handle is resolved by the Mac OS X dynamic linker.
    if (GV->getName() == "__dso_handle")
      return (void*)&__dso_handle;
    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName().c_str());
    if (Ptr == 0) {
      std::cerr << "Could not resolve external global address: "
                << GV->getName() << "\n";
      abort();
    }
  } else {
    // If the global hasn't been emitted to memory yet, allocate space.  We will
    // actually initialize the global after current function has finished
    // compilation.
    const Type *GlobalType = GV->getType()->getElementType();
    size_t S = getTargetData()->getTypeSize(GlobalType);
    size_t A = getTargetData()->getTypeAlignment(GlobalType);
    if (A <= 8) {
      Ptr = malloc(S);
    } else {
      // Allocate S+A bytes of memory, then use an aligned pointer within that
      // space.
      Ptr = malloc(S+A);
      unsigned MisAligned = ((intptr_t)Ptr & (A-1));
      Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0);
    }
    state.getPendingGlobals(locked).push_back(GV);
  }
  addGlobalMapping(GV, Ptr);
  return Ptr;
}

/// recompileAndRelinkFunction - This method is used to force a function
/// which has already been compiled, to be compiled again, possibly
/// after it has been modified. Then the entry to the old copy is overwritten
/// with a branch to the new copy. If there was no old copy, this acts
/// just like JIT::getPointerToFunction().
///
void *JIT::recompileAndRelinkFunction(Function *F) {
  void *OldAddr = getPointerToGlobalIfAvailable(F);

  // If it's not already compiled there is no reason to patch it up.
  if (OldAddr == 0) { return getPointerToFunction(F); }

  // Delete the old function mapping.
  addGlobalMapping(F, 0);

  // Recodegen the function
  runJITOnFunction(F);

  // Update state, forward the old function to the new function.
  void *Addr = getPointerToGlobalIfAvailable(F);
  assert(Addr && "Code generation didn't add function to GlobalAddress table!");
  TJI.replaceMachineCodeForFunction(OldAddr, Addr);
  return Addr;
}

<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkCollectPolyData.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "vtkCollectPolyData.h"

#include "vtkAppendPolyData.h"
#include "vtkCellData.h"
#include "vtkMultiProcessController.h"
#include "vtkSocketController.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"

vtkCxxRevisionMacro(vtkCollectPolyData, "1.14");
vtkStandardNewMacro(vtkCollectPolyData);

vtkCxxSetObjectMacro(vtkCollectPolyData,Controller, vtkMultiProcessController);
vtkCxxSetObjectMacro(vtkCollectPolyData,SocketController, vtkSocketController);

//----------------------------------------------------------------------------
vtkCollectPolyData::vtkCollectPolyData()
{
  this->PassThrough = 0;
  this->SocketController = NULL;

  // Controller keeps a reference to this object as well.
  this->Controller = NULL;
  this->SetController(vtkMultiProcessController::GetGlobalController());
}

//----------------------------------------------------------------------------
vtkCollectPolyData::~vtkCollectPolyData()
{
  this->SetController(0);
  this->SetSocketController(0);
}

//----------------------------------------------------------------------------
void vtkCollectPolyData::ExecuteInformation()
{
  if (this->GetOutput() == NULL)
    {
    vtkErrorMacro("Missing output");
    return;
    }
  this->GetOutput()->SetMaximumNumberOfPieces(-1);
}

//--------------------------------------------------------------------------
void vtkCollectPolyData::ComputeInputUpdateExtents(vtkDataObject *output)
{
  vtkPolyData *input = this->GetInput();
  int piece = output->GetUpdatePiece();
  int numPieces = output->GetUpdateNumberOfPieces();
  int ghostLevel = output->GetUpdateGhostLevel();

  if (input == NULL)
    {
    return;
    }
  input->SetUpdatePiece(piece);
  input->SetUpdateNumberOfPieces(numPieces);
  input->SetUpdateGhostLevel(ghostLevel);
}

//----------------------------------------------------------------------------
void vtkCollectPolyData::ExecuteData(vtkDataObject*)
{
  vtkPolyData *input = this->GetInput();
  vtkPolyData *output = this->GetOutput();
  unsigned long size=0;
  unsigned long tmp=0;
  int numProcs, myId;
  int idx;

  if (input == NULL)
    {
    vtkErrorMacro("Input has not been set.");
    return;
    }

  if (this->Controller == NULL && this->SocketController == NULL)
    { // Running as a single process.
    output->CopyStructure(input);
    output->GetPointData()->PassData(input->GetPointData());
    output->GetCellData()->PassData(input->GetCellData());
    return;
    }

  if (this->Controller == NULL && this->SocketController != NULL)
    { // This is a client.  We assume no data on client for input.
    if ( ! this->PassThrough)
      {
      vtkPolyData *pd = NULL;;
      pd = vtkPolyData::New();
      this->SocketController->Receive(pd, 1, 121767);
      output->CopyStructure(pd);
      output->GetPointData()->PassData(pd->GetPointData());
      output->GetCellData()->PassData(pd->GetCellData());
      pd->Delete();
      pd = NULL;
      }
    // If not collected, output will be empty from initialization.
    return;
    }

  myId = this->Controller->GetLocalProcessId();
  numProcs = this->Controller->GetNumberOfProcesses();

  if (this->PassThrough)
    {
    // Just copy and return (no collection).
    output->CopyStructure(input);
    output->GetPointData()->PassData(input->GetPointData());
    output->GetCellData()->PassData(input->GetCellData());
    return;
    }

  // Collect.
  vtkAppendPolyData *append = vtkAppendPolyData::New();
  vtkPolyData *pd = NULL;;

  if (myId == 0)
    {
    pd = vtkPolyData::New();
    pd->CopyStructure(input);
    pd->GetPointData()->PassData(input->GetPointData());
    pd->GetCellData()->PassData(input->GetCellData());
    append->AddInput(pd);
    pd->Delete();
    for (idx = 1; idx < numProcs; ++idx)
      {
      pd = vtkPolyData::New();
      this->Controller->Receive(pd, idx, 121767);
      append->AddInput(pd);
      pd->Delete();
      pd = NULL;
      }
    append->Update();
    input = append->GetOutput();
    if (this->SocketController)
      { // Send collected data onto client.
      this->SocketController->Send(input, 1, 121767);
      // output will be empty.
      }
    else
      { // No client. Keep the output here.
      output->CopyStructure(input);
      output->GetPointData()->PassData(input->GetPointData());
      output->GetCellData()->PassData(input->GetCellData());
      }
    append->Delete();
    append = NULL;
    }
  else
    {
    this->Controller->Send(input, 0, 121767);
    append->Delete();
    append = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkCollectPolyData::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "PassThough: " << this->PassThrough << endl;
  os << indent << "Controller: (" << this->Controller << ")\n";
  os << indent << "SocketController: (" << this->SocketController << ")\n";
}

<commit_msg>ERR:Removed unused variables<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkCollectPolyData.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "vtkCollectPolyData.h"

#include "vtkAppendPolyData.h"
#include "vtkCellData.h"
#include "vtkMultiProcessController.h"
#include "vtkSocketController.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"

vtkCxxRevisionMacro(vtkCollectPolyData, "1.15");
vtkStandardNewMacro(vtkCollectPolyData);

vtkCxxSetObjectMacro(vtkCollectPolyData,Controller, vtkMultiProcessController);
vtkCxxSetObjectMacro(vtkCollectPolyData,SocketController, vtkSocketController);

//----------------------------------------------------------------------------
vtkCollectPolyData::vtkCollectPolyData()
{
  this->PassThrough = 0;
  this->SocketController = NULL;

  // Controller keeps a reference to this object as well.
  this->Controller = NULL;
  this->SetController(vtkMultiProcessController::GetGlobalController());
}

//----------------------------------------------------------------------------
vtkCollectPolyData::~vtkCollectPolyData()
{
  this->SetController(0);
  this->SetSocketController(0);
}

//----------------------------------------------------------------------------
void vtkCollectPolyData::ExecuteInformation()
{
  if (this->GetOutput() == NULL)
    {
    vtkErrorMacro("Missing output");
    return;
    }
  this->GetOutput()->SetMaximumNumberOfPieces(-1);
}

//--------------------------------------------------------------------------
void vtkCollectPolyData::ComputeInputUpdateExtents(vtkDataObject *output)
{
  vtkPolyData *input = this->GetInput();
  int piece = output->GetUpdatePiece();
  int numPieces = output->GetUpdateNumberOfPieces();
  int ghostLevel = output->GetUpdateGhostLevel();

  if (input == NULL)
    {
    return;
    }
  input->SetUpdatePiece(piece);
  input->SetUpdateNumberOfPieces(numPieces);
  input->SetUpdateGhostLevel(ghostLevel);
}

//----------------------------------------------------------------------------
void vtkCollectPolyData::ExecuteData(vtkDataObject*)
{
  vtkPolyData *input = this->GetInput();
  vtkPolyData *output = this->GetOutput();
  int numProcs, myId;
  int idx;

  if (input == NULL)
    {
    vtkErrorMacro("Input has not been set.");
    return;
    }

  if (this->Controller == NULL && this->SocketController == NULL)
    { // Running as a single process.
    output->CopyStructure(input);
    output->GetPointData()->PassData(input->GetPointData());
    output->GetCellData()->PassData(input->GetCellData());
    return;
    }

  if (this->Controller == NULL && this->SocketController != NULL)
    { // This is a client.  We assume no data on client for input.
    if ( ! this->PassThrough)
      {
      vtkPolyData *pd = NULL;;
      pd = vtkPolyData::New();
      this->SocketController->Receive(pd, 1, 121767);
      output->CopyStructure(pd);
      output->GetPointData()->PassData(pd->GetPointData());
      output->GetCellData()->PassData(pd->GetCellData());
      pd->Delete();
      pd = NULL;
      }
    // If not collected, output will be empty from initialization.
    return;
    }

  myId = this->Controller->GetLocalProcessId();
  numProcs = this->Controller->GetNumberOfProcesses();

  if (this->PassThrough)
    {
    // Just copy and return (no collection).
    output->CopyStructure(input);
    output->GetPointData()->PassData(input->GetPointData());
    output->GetCellData()->PassData(input->GetCellData());
    return;
    }

  // Collect.
  vtkAppendPolyData *append = vtkAppendPolyData::New();
  vtkPolyData *pd = NULL;;

  if (myId == 0)
    {
    pd = vtkPolyData::New();
    pd->CopyStructure(input);
    pd->GetPointData()->PassData(input->GetPointData());
    pd->GetCellData()->PassData(input->GetCellData());
    append->AddInput(pd);
    pd->Delete();
    for (idx = 1; idx < numProcs; ++idx)
      {
      pd = vtkPolyData::New();
      this->Controller->Receive(pd, idx, 121767);
      append->AddInput(pd);
      pd->Delete();
      pd = NULL;
      }
    append->Update();
    input = append->GetOutput();
    if (this->SocketController)
      { // Send collected data onto client.
      this->SocketController->Send(input, 1, 121767);
      // output will be empty.
      }
    else
      { // No client. Keep the output here.
      output->CopyStructure(input);
      output->GetPointData()->PassData(input->GetPointData());
      output->GetCellData()->PassData(input->GetCellData());
      }
    append->Delete();
    append = NULL;
    }
  else
    {
    this->Controller->Send(input, 0, 121767);
    append->Delete();
    append = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkCollectPolyData::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "PassThough: " << this->PassThrough << endl;
  os << indent << "Controller: (" << this->Controller << ")\n";
  os << indent << "SocketController: (" << this->SocketController << ")\n";
}

<|endoftext|>


<commit_before>//===--- IndexRecordWriter.cpp - Index record serialization ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Index/IndexRecordWriter.h"
#include "IndexDataStoreUtils.h"
#include "indexstore/indexstore.h"
#include "clang/Index/IndexDataStoreSymbolUtils.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::index;
using namespace clang::index::store;
using namespace llvm;

using writer::OpaqueDecl;

namespace {
struct DeclInfo {
  OpaqueDecl D;
  SymbolRoleSet Roles;
  SymbolRoleSet RelatedRoles;
};

struct OccurrenceInfo {
  unsigned DeclID;
  OpaqueDecl D;
  SymbolRoleSet Roles;
  unsigned Line;
  unsigned Column;
  SmallVector<std::pair<writer::SymbolRelation, unsigned>, 4> Related;
};

struct RecordState {
  std::string RecordPath;
  SmallString<512> Buffer;
  BitstreamWriter Stream;

  DenseMap<OpaqueDecl, unsigned> IndexForDecl;
  std::vector<DeclInfo> Decls;
  std::vector<OccurrenceInfo> Occurrences;

  RecordState(std::string &&RecordPath)
      : RecordPath(std::move(RecordPath)), Stream(Buffer) {}
};
} // end anonymous namespace

static void writeBlockInfo(BitstreamWriter &Stream) {
  RecordData Record;

  Stream.EnterBlockInfoBlock();
#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record)
#define RECORD(X) emitRecordID(X, #X, Stream, Record)

  BLOCK(REC_VERSION_BLOCK);
  RECORD(REC_VERSION);

  BLOCK(REC_DECLS_BLOCK);
  RECORD(REC_DECLINFO);

  BLOCK(REC_DECLOFFSETS_BLOCK);
  RECORD(REC_DECLOFFSETS);

  BLOCK(REC_DECLOCCURRENCES_BLOCK);
  RECORD(REC_DECLOCCURRENCE);

#undef RECORD
#undef BLOCK
  Stream.ExitBlock();
}

static void writeVersionInfo(BitstreamWriter &Stream) {
  using namespace llvm::sys;

  Stream.EnterSubblock(REC_VERSION_BLOCK_ID, 3);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_VERSION));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Store format version
  unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

  RecordData Record;
  Record.push_back(REC_VERSION);
  Record.push_back(STORE_FORMAT_VERSION);
  Stream.EmitRecordWithAbbrev(AbbrevCode, Record);

  Stream.ExitBlock();
}

template <typename T, typename Allocator>
static StringRef data(const std::vector<T, Allocator> &v) {
  if (v.empty())
    return StringRef();
  return StringRef(reinterpret_cast<const char *>(&v[0]), sizeof(T) * v.size());
}

template <typename T> static StringRef data(const SmallVectorImpl<T> &v) {
  return StringRef(reinterpret_cast<const char *>(v.data()),
                   sizeof(T) * v.size());
}

static void writeDecls(BitstreamWriter &Stream, ArrayRef<DeclInfo> Decls,
                       ArrayRef<OccurrenceInfo> Occurrences,
                       writer::SymbolWriterCallback GetSymbolForDecl) {
  SmallVector<uint32_t, 32> DeclOffsets;
  DeclOffsets.reserve(Decls.size());

  //===--------------------------------------------------------------------===//
  // DECLS_BLOCK_ID
  //===--------------------------------------------------------------------===//

  Stream.EnterSubblock(REC_DECLS_BLOCK_ID, 3);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_DECLINFO));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 5)); // Kind
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 5)); // SubKind
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 5)); // Language
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolPropertyBitNum)); // Properties
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolRoleBitNum)); // Roles
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolRoleBitNum)); // Related Roles
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Length of name in block
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Length of USR in block
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + USR + CodeGen symbol name
  unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

#ifndef NDEBUG
  StringSet<> USRSet;
#endif

  RecordData Record;
  llvm::SmallString<256> Blob;
  llvm::SmallString<256> Scratch;
  for (auto &Info : Decls) {
    DeclOffsets.push_back(Stream.GetCurrentBitNo());
    Blob.clear();
    Scratch.clear();

    writer::Symbol SymInfo = GetSymbolForDecl(Info.D, Scratch);
    assert(SymInfo.SymInfo.Kind != SymbolKind::Unknown);
    assert(!SymInfo.USR.empty() && "Recorded decl without USR!");

    Blob += SymInfo.Name;
    Blob += SymInfo.USR;
    Blob += SymInfo.CodeGenName;

#ifndef NDEBUG
    bool IsNew = USRSet.insert(SymInfo.USR).second;
    if (!IsNew) {
      llvm::errs() << "Index: Duplicate USR! " << SymInfo.USR << "\n";
      // FIXME: print more information so it's easier to find the declaration.
    }
#endif

    Record.clear();
    Record.push_back(REC_DECLINFO);
    Record.push_back(getIndexStoreKind(SymInfo.SymInfo.Kind));
    Record.push_back(getIndexStoreSubKind(SymInfo.SymInfo.SubKind));
    Record.push_back(getIndexStoreLang(SymInfo.SymInfo.Lang));
    Record.push_back(getIndexStoreProperties(SymInfo.SymInfo.Properties));
    Record.push_back(getIndexStoreRoles(Info.Roles));
    Record.push_back(getIndexStoreRoles(Info.RelatedRoles));
    Record.push_back(SymInfo.Name.size());
    Record.push_back(SymInfo.USR.size());
    Stream.EmitRecordWithBlob(AbbrevCode, Record, Blob);
  }

  Stream.ExitBlock();

  //===--------------------------------------------------------------------===//
  // DECLOFFSETS_BLOCK_ID
  //===--------------------------------------------------------------------===//

  Stream.EnterSubblock(REC_DECLOFFSETS_BLOCK_ID, 3);

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_DECLOFFSETS));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of Decls
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Offsets array
  AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

  Record.clear();
  Record.push_back(REC_DECLOFFSETS);
  Record.push_back(DeclOffsets.size());
  Stream.EmitRecordWithBlob(AbbrevCode, Record, data(DeclOffsets));

  Stream.ExitBlock();

  //===--------------------------------------------------------------------===//
  // DECLOCCURRENCES_BLOCK_ID
  //===--------------------------------------------------------------------===//

  Stream.EnterSubblock(REC_DECLOCCURRENCES_BLOCK_ID, 3);

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_DECLOCCURRENCE));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Decl ID
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolRoleBitNum)); // Roles
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Line
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Column
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Num related
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); // Related Roles/IDs
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Roles or ID
  AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

  for (auto &Occur : Occurrences) {
    Record.clear();
    Record.push_back(REC_DECLOCCURRENCE);
    Record.push_back(Occur.DeclID);
    Record.push_back(getIndexStoreRoles(Occur.Roles));
    Record.push_back(Occur.Line);
    Record.push_back(Occur.Column);
    Record.push_back(Occur.Related.size());
    for (auto &Rel : Occur.Related) {
      Record.push_back(getIndexStoreRoles(Rel.first.Roles));
      Record.push_back(Rel.second);
    }
    Stream.EmitRecordWithAbbrev(AbbrevCode, Record);
  }
  Stream.ExitBlock();
}

IndexRecordWriter::IndexRecordWriter(StringRef IndexPath)
    : RecordsPath(IndexPath) {
  store::appendRecordSubDir(RecordsPath);
}

IndexRecordWriter::Result
IndexRecordWriter::beginRecord(StringRef Filename, hash_code RecordHash,
                               std::string &Error, std::string *OutRecordFile) {
  using namespace llvm::sys;
  assert(!Record && "called beginRecord before calling endRecord on previous");

  std::string RecordName;
  {
    llvm::raw_string_ostream RN(RecordName);
    RN << path::filename(Filename);
    RN << "-" << APInt(64, RecordHash).toString(36, /*Signed=*/false);
  }
  SmallString<256> RecordPath = RecordsPath.str();
  appendInteriorRecordPath(RecordName, RecordPath);

  if (OutRecordFile)
    *OutRecordFile = RecordName;

  if (std::error_code EC =
          fs::access(RecordPath.c_str(), fs::AccessMode::Exist)) {
    if (EC != errc::no_such_file_or_directory) {
      llvm::raw_string_ostream Err(Error);
      Err << "could not access record '" << RecordPath
          << "': " << EC.message();
      return Result::Failure;
    }
  } else {
    return Result::AlreadyExists;
  }

  // Write the record header.
  auto *State = new RecordState(RecordPath.str());
  Record = State;
  llvm::BitstreamWriter &Stream = State->Stream;
  Stream.Emit('I', 8);
  Stream.Emit('D', 8);
  Stream.Emit('X', 8);
  Stream.Emit('R', 8);

  writeBlockInfo(Stream);
  writeVersionInfo(Stream);

  return Result::Success;
}

IndexRecordWriter::Result
IndexRecordWriter::endRecord(std::string &Error,
                             writer::SymbolWriterCallback GetSymbolForDecl) {
  assert(Record && "called endRecord without calling beginRecord");
  auto &State = *static_cast<RecordState *>(Record);
  Record = nullptr;
  struct ScopedDelete {
    RecordState *S;
    ScopedDelete(RecordState *S) : S(S) {}
    ~ScopedDelete() { delete S; }
  } Deleter(&State);

  if (!State.Decls.empty()) {
    writeDecls(State.Stream, State.Decls, State.Occurrences, GetSymbolForDecl);
  }

  if (std::error_code EC = sys::fs::create_directory(sys::path::parent_path(State.RecordPath))) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to create directory '" << sys::path::parent_path(State.RecordPath) << "': " << EC.message();
    return Result::Failure;
  }

  // Create a unique file to write to so that we can move the result into place
  // atomically. If this process crashes we don't want to interfere with any
  // other concurrent processes.
  SmallString<128> TempPath(State.RecordPath);
  TempPath += "-temp-%%%%%%%%";
  int TempFD;
  if (sys::fs::createUniqueFile(TempPath.str(), TempFD, TempPath)) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to create temporary file: " << TempPath;
    return Result::Failure;
  }

  raw_fd_ostream OS(TempFD, /*shouldClose=*/true);
  OS.write(State.Buffer.data(), State.Buffer.size());
  OS.close();

  if (OS.has_error()) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to write '" << TempPath << "': " << OS.error().message();
    OS.clear_error();
    return Result::Failure;
  }

  // Atomically move the unique file into place.
  if (std::error_code EC =
          sys::fs::rename(TempPath.c_str(), State.RecordPath.c_str())) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to rename '" << TempPath << "' to '" << State.RecordPath << "': " << EC.message();
    return Result::Failure;
  }

  return Result::Success;
}

void IndexRecordWriter::addOccurrence(
    OpaqueDecl D, SymbolRoleSet Roles, unsigned Line, unsigned Column,
    ArrayRef<writer::SymbolRelation> Related) {
  assert(Record && "called addOccurrence without calling beginRecord");
  auto &State = *static_cast<RecordState *>(Record);

  auto insertDecl = [&](OpaqueDecl D, SymbolRoleSet Roles,
                        SymbolRoleSet RelatedRoles) -> unsigned {
    auto Insert =
        State.IndexForDecl.insert(std::make_pair(D, State.Decls.size()));
    unsigned Index = Insert.first->second;

    if (Insert.second) {
      State.Decls.push_back(DeclInfo{D, Roles, RelatedRoles});
    } else {
      State.Decls[Index].Roles |= Roles;
      State.Decls[Index].RelatedRoles |= RelatedRoles;
    }
    return Index + 1;
  };

  unsigned DeclID = insertDecl(D, Roles, SymbolRoleSet());

  decltype(OccurrenceInfo::Related) RelatedDecls;
  RelatedDecls.reserve(Related.size());
  for (auto &Rel : Related) {
    unsigned ID = insertDecl(Rel.RelatedSymbol, SymbolRoleSet(), Rel.Roles);
    RelatedDecls.emplace_back(Rel, ID);
  }

  State.Occurrences.push_back(
      OccurrenceInfo{DeclID, D, Roles, Line, Column, std::move(RelatedDecls)});
}
<commit_msg>[index/store] Put the USR validation checking logging behind an environment variable<commit_after>//===--- IndexRecordWriter.cpp - Index record serialization ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Index/IndexRecordWriter.h"
#include "IndexDataStoreUtils.h"
#include "indexstore/indexstore.h"
#include "clang/Index/IndexDataStoreSymbolUtils.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::index;
using namespace clang::index::store;
using namespace llvm;

using writer::OpaqueDecl;

namespace {
struct DeclInfo {
  OpaqueDecl D;
  SymbolRoleSet Roles;
  SymbolRoleSet RelatedRoles;
};

struct OccurrenceInfo {
  unsigned DeclID;
  OpaqueDecl D;
  SymbolRoleSet Roles;
  unsigned Line;
  unsigned Column;
  SmallVector<std::pair<writer::SymbolRelation, unsigned>, 4> Related;
};

struct RecordState {
  std::string RecordPath;
  SmallString<512> Buffer;
  BitstreamWriter Stream;

  DenseMap<OpaqueDecl, unsigned> IndexForDecl;
  std::vector<DeclInfo> Decls;
  std::vector<OccurrenceInfo> Occurrences;

  RecordState(std::string &&RecordPath)
      : RecordPath(std::move(RecordPath)), Stream(Buffer) {}
};
} // end anonymous namespace

static void writeBlockInfo(BitstreamWriter &Stream) {
  RecordData Record;

  Stream.EnterBlockInfoBlock();
#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record)
#define RECORD(X) emitRecordID(X, #X, Stream, Record)

  BLOCK(REC_VERSION_BLOCK);
  RECORD(REC_VERSION);

  BLOCK(REC_DECLS_BLOCK);
  RECORD(REC_DECLINFO);

  BLOCK(REC_DECLOFFSETS_BLOCK);
  RECORD(REC_DECLOFFSETS);

  BLOCK(REC_DECLOCCURRENCES_BLOCK);
  RECORD(REC_DECLOCCURRENCE);

#undef RECORD
#undef BLOCK
  Stream.ExitBlock();
}

static void writeVersionInfo(BitstreamWriter &Stream) {
  using namespace llvm::sys;

  Stream.EnterSubblock(REC_VERSION_BLOCK_ID, 3);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_VERSION));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Store format version
  unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

  RecordData Record;
  Record.push_back(REC_VERSION);
  Record.push_back(STORE_FORMAT_VERSION);
  Stream.EmitRecordWithAbbrev(AbbrevCode, Record);

  Stream.ExitBlock();
}

template <typename T, typename Allocator>
static StringRef data(const std::vector<T, Allocator> &v) {
  if (v.empty())
    return StringRef();
  return StringRef(reinterpret_cast<const char *>(&v[0]), sizeof(T) * v.size());
}

template <typename T> static StringRef data(const SmallVectorImpl<T> &v) {
  return StringRef(reinterpret_cast<const char *>(v.data()),
                   sizeof(T) * v.size());
}

static void writeDecls(BitstreamWriter &Stream, ArrayRef<DeclInfo> Decls,
                       ArrayRef<OccurrenceInfo> Occurrences,
                       writer::SymbolWriterCallback GetSymbolForDecl) {
  SmallVector<uint32_t, 32> DeclOffsets;
  DeclOffsets.reserve(Decls.size());

  //===--------------------------------------------------------------------===//
  // DECLS_BLOCK_ID
  //===--------------------------------------------------------------------===//

  Stream.EnterSubblock(REC_DECLS_BLOCK_ID, 3);

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_DECLINFO));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 5)); // Kind
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 5)); // SubKind
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 5)); // Language
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolPropertyBitNum)); // Properties
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolRoleBitNum)); // Roles
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolRoleBitNum)); // Related Roles
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Length of name in block
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Length of USR in block
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + USR + CodeGen symbol name
  unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

#ifndef NDEBUG
  StringSet<> USRSet;
  bool enableValidation = getenv("CLANG_INDEX_VALIDATION_CHECKS") != nullptr;
#endif

  RecordData Record;
  llvm::SmallString<256> Blob;
  llvm::SmallString<256> Scratch;
  for (auto &Info : Decls) {
    DeclOffsets.push_back(Stream.GetCurrentBitNo());
    Blob.clear();
    Scratch.clear();

    writer::Symbol SymInfo = GetSymbolForDecl(Info.D, Scratch);
    assert(SymInfo.SymInfo.Kind != SymbolKind::Unknown);
    assert(!SymInfo.USR.empty() && "Recorded decl without USR!");

    Blob += SymInfo.Name;
    Blob += SymInfo.USR;
    Blob += SymInfo.CodeGenName;

#ifndef NDEBUG
    if (enableValidation) {
      bool IsNew = USRSet.insert(SymInfo.USR).second;
      if (!IsNew) {
        llvm::errs() << "Index: Duplicate USR! " << SymInfo.USR << "\n";
        // FIXME: print more information so it's easier to find the declaration.
      }
    }
#endif

    Record.clear();
    Record.push_back(REC_DECLINFO);
    Record.push_back(getIndexStoreKind(SymInfo.SymInfo.Kind));
    Record.push_back(getIndexStoreSubKind(SymInfo.SymInfo.SubKind));
    Record.push_back(getIndexStoreLang(SymInfo.SymInfo.Lang));
    Record.push_back(getIndexStoreProperties(SymInfo.SymInfo.Properties));
    Record.push_back(getIndexStoreRoles(Info.Roles));
    Record.push_back(getIndexStoreRoles(Info.RelatedRoles));
    Record.push_back(SymInfo.Name.size());
    Record.push_back(SymInfo.USR.size());
    Stream.EmitRecordWithBlob(AbbrevCode, Record, Blob);
  }

  Stream.ExitBlock();

  //===--------------------------------------------------------------------===//
  // DECLOFFSETS_BLOCK_ID
  //===--------------------------------------------------------------------===//

  Stream.EnterSubblock(REC_DECLOFFSETS_BLOCK_ID, 3);

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_DECLOFFSETS));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of Decls
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Offsets array
  AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

  Record.clear();
  Record.push_back(REC_DECLOFFSETS);
  Record.push_back(DeclOffsets.size());
  Stream.EmitRecordWithBlob(AbbrevCode, Record, data(DeclOffsets));

  Stream.ExitBlock();

  //===--------------------------------------------------------------------===//
  // DECLOCCURRENCES_BLOCK_ID
  //===--------------------------------------------------------------------===//

  Stream.EnterSubblock(REC_DECLOCCURRENCES_BLOCK_ID, 3);

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(REC_DECLOCCURRENCE));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Decl ID
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, SymbolRoleBitNum)); // Roles
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Line
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Column
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Num related
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); // Related Roles/IDs
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Roles or ID
  AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

  for (auto &Occur : Occurrences) {
    Record.clear();
    Record.push_back(REC_DECLOCCURRENCE);
    Record.push_back(Occur.DeclID);
    Record.push_back(getIndexStoreRoles(Occur.Roles));
    Record.push_back(Occur.Line);
    Record.push_back(Occur.Column);
    Record.push_back(Occur.Related.size());
    for (auto &Rel : Occur.Related) {
      Record.push_back(getIndexStoreRoles(Rel.first.Roles));
      Record.push_back(Rel.second);
    }
    Stream.EmitRecordWithAbbrev(AbbrevCode, Record);
  }
  Stream.ExitBlock();
}

IndexRecordWriter::IndexRecordWriter(StringRef IndexPath)
    : RecordsPath(IndexPath) {
  store::appendRecordSubDir(RecordsPath);
}

IndexRecordWriter::Result
IndexRecordWriter::beginRecord(StringRef Filename, hash_code RecordHash,
                               std::string &Error, std::string *OutRecordFile) {
  using namespace llvm::sys;
  assert(!Record && "called beginRecord before calling endRecord on previous");

  std::string RecordName;
  {
    llvm::raw_string_ostream RN(RecordName);
    RN << path::filename(Filename);
    RN << "-" << APInt(64, RecordHash).toString(36, /*Signed=*/false);
  }
  SmallString<256> RecordPath = RecordsPath.str();
  appendInteriorRecordPath(RecordName, RecordPath);

  if (OutRecordFile)
    *OutRecordFile = RecordName;

  if (std::error_code EC =
          fs::access(RecordPath.c_str(), fs::AccessMode::Exist)) {
    if (EC != errc::no_such_file_or_directory) {
      llvm::raw_string_ostream Err(Error);
      Err << "could not access record '" << RecordPath
          << "': " << EC.message();
      return Result::Failure;
    }
  } else {
    return Result::AlreadyExists;
  }

  // Write the record header.
  auto *State = new RecordState(RecordPath.str());
  Record = State;
  llvm::BitstreamWriter &Stream = State->Stream;
  Stream.Emit('I', 8);
  Stream.Emit('D', 8);
  Stream.Emit('X', 8);
  Stream.Emit('R', 8);

  writeBlockInfo(Stream);
  writeVersionInfo(Stream);

  return Result::Success;
}

IndexRecordWriter::Result
IndexRecordWriter::endRecord(std::string &Error,
                             writer::SymbolWriterCallback GetSymbolForDecl) {
  assert(Record && "called endRecord without calling beginRecord");
  auto &State = *static_cast<RecordState *>(Record);
  Record = nullptr;
  struct ScopedDelete {
    RecordState *S;
    ScopedDelete(RecordState *S) : S(S) {}
    ~ScopedDelete() { delete S; }
  } Deleter(&State);

  if (!State.Decls.empty()) {
    writeDecls(State.Stream, State.Decls, State.Occurrences, GetSymbolForDecl);
  }

  if (std::error_code EC = sys::fs::create_directory(sys::path::parent_path(State.RecordPath))) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to create directory '" << sys::path::parent_path(State.RecordPath) << "': " << EC.message();
    return Result::Failure;
  }

  // Create a unique file to write to so that we can move the result into place
  // atomically. If this process crashes we don't want to interfere with any
  // other concurrent processes.
  SmallString<128> TempPath(State.RecordPath);
  TempPath += "-temp-%%%%%%%%";
  int TempFD;
  if (sys::fs::createUniqueFile(TempPath.str(), TempFD, TempPath)) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to create temporary file: " << TempPath;
    return Result::Failure;
  }

  raw_fd_ostream OS(TempFD, /*shouldClose=*/true);
  OS.write(State.Buffer.data(), State.Buffer.size());
  OS.close();

  if (OS.has_error()) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to write '" << TempPath << "': " << OS.error().message();
    OS.clear_error();
    return Result::Failure;
  }

  // Atomically move the unique file into place.
  if (std::error_code EC =
          sys::fs::rename(TempPath.c_str(), State.RecordPath.c_str())) {
    llvm::raw_string_ostream Err(Error);
    Err << "failed to rename '" << TempPath << "' to '" << State.RecordPath << "': " << EC.message();
    return Result::Failure;
  }

  return Result::Success;
}

void IndexRecordWriter::addOccurrence(
    OpaqueDecl D, SymbolRoleSet Roles, unsigned Line, unsigned Column,
    ArrayRef<writer::SymbolRelation> Related) {
  assert(Record && "called addOccurrence without calling beginRecord");
  auto &State = *static_cast<RecordState *>(Record);

  auto insertDecl = [&](OpaqueDecl D, SymbolRoleSet Roles,
                        SymbolRoleSet RelatedRoles) -> unsigned {
    auto Insert =
        State.IndexForDecl.insert(std::make_pair(D, State.Decls.size()));
    unsigned Index = Insert.first->second;

    if (Insert.second) {
      State.Decls.push_back(DeclInfo{D, Roles, RelatedRoles});
    } else {
      State.Decls[Index].Roles |= Roles;
      State.Decls[Index].RelatedRoles |= RelatedRoles;
    }
    return Index + 1;
  };

  unsigned DeclID = insertDecl(D, Roles, SymbolRoleSet());

  decltype(OccurrenceInfo::Related) RelatedDecls;
  RelatedDecls.reserve(Related.size());
  for (auto &Rel : Related) {
    unsigned ID = insertDecl(Rel.RelatedSymbol, SymbolRoleSet(), Rel.Roles);
    RelatedDecls.emplace_back(Rel, ID);
  }

  State.Occurrences.push_back(
      OccurrenceInfo{DeclID, D, Roles, Line, Column, std::move(RelatedDecls)});
}
<|endoftext|>