<commit_before>/*************************************************************************
 *
 *  $RCSfile: PageMasterImportPropMapper.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: sab $ $Date: 2000-10-26 10:35:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _XMLOFF_PAGEMASTERIMPORTPROPMAPPER_HXX
#include "PageMasterImportPropMapper.hxx"
#endif
#ifndef _XMLOFF_PAGEMASTERPROPMAPPER_HXX
#include "PageMasterPropMapper.hxx"
#endif
#ifndef _XMLOFF_PAGEMASTERSTYLEMAP_HXX
#include "PageMasterStyleMap.hxx"
#endif

#ifndef _XMLOFF_PROPMAPPINGTYPES_HXX
#include <xmloff/maptype.hxx>
#endif

using namespace ::com::sun::star;

PageMasterImportPropertyMapper::PageMasterImportPropertyMapper(
        const UniReference< XMLPropertySetMapper >& rMapper ) :
    SvXMLImportPropertyMapper( rMapper )
{
}

PageMasterImportPropertyMapper::~PageMasterImportPropertyMapper()
{
}

/*sal_Bool PageMasterImportPropertyMapper::handleSpecialItem(
        XMLPropertyState& rProperty,
        ::std::vector< XMLPropertyState >& rProperties,
        const ::rtl::OUString& rValue,
        const SvXMLUnitConverter& rUnitConverter,
        const SvXMLNamespaceMap& rNamespaceMap ) const
{
    return sal_True;
}*/

/*sal_Bool PageMasterImportPropertyMapper::handleNoItem(
        sal_Int32 nIndex,
        ::std::vector< XMLPropertyState >& rProperties,
        const ::rtl::OUString& rValue,
        const SvXMLUnitConverter& rUnitConverter,
        const SvXMLNamespaceMap& rNamespaceMap ) const
{
    return sal_True;
}*/

void PageMasterImportPropertyMapper::finished(::std::vector< XMLPropertyState >& rProperties, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
{
    SvXMLImportPropertyMapper::finished(rProperties, nStartIndex, nEndIndex);
    XMLPropertyState* pAllPaddingProperty = NULL;
    XMLPropertyState* pAllBorderProperty = NULL;
    XMLPropertyState* pAllBorderWidthProperty = NULL;
    XMLPropertyState* pAllHeaderPaddingProperty = NULL;
    XMLPropertyState* pAllHeaderBorderProperty = NULL;
    XMLPropertyState* pAllHeaderBorderWidthProperty = NULL;
    XMLPropertyState* pAllFooterPaddingProperty = NULL;
    XMLPropertyState* pAllFooterBorderProperty = NULL;
    XMLPropertyState* pAllFooterBorderWidthProperty = NULL;
    XMLPropertyState* pHeaderHeight = NULL;
    XMLPropertyState* pHeaderMinHeight = NULL;
    XMLPropertyState* pFooterHeight = NULL;
    XMLPropertyState* pFooterMinHeight = NULL;
    ::std::vector< XMLPropertyState >::iterator i = rProperties.begin();
    for (i; i != rProperties.end(); i++)
    {
        sal_Int16 nContextID = getPropertySetMapper()->GetEntryContextId(i->mnIndex);
        switch (nContextID)
        {
            case CTF_PM_PADDINGALL :
            {
                pAllPaddingProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_BORDERALL :
            {
                pAllBorderProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_BORDERWIDTHALL :
            {
                pAllBorderWidthProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_HEADERPADDINGALL :
            {
                pAllHeaderPaddingProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_HEADERBORDERALL :
            {
                pAllHeaderBorderProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_HEADERBORDERWIDTHALL :
            {
                pAllHeaderBorderWidthProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_FOOTERPADDINGALL :
            {
                pAllFooterPaddingProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_FOOTERBORDERALL :
            {
                pAllFooterBorderProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_FOOTERBORDERWIDTHALL :
            {
                pAllFooterBorderWidthProperty = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_HEADERHEIGHT :
            {
                pHeaderHeight = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_HEADERMINHEIGHT :
            {
                pHeaderMinHeight = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_FOOTERHEIGHT :
            {
                pFooterHeight = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
            case CTF_PM_FOOTERMINHEIGHT :
            {
                pFooterMinHeight = new XMLPropertyState(i->mnIndex, i->maValue);
            }
            break;
        }
    }
    if (pAllPaddingProperty)
    {
        sal_Int32 nIndex = pAllPaddingProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllPaddingProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllBorderProperty)
    {
        sal_Int32 nIndex = pAllBorderProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllBorderProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllBorderWidthProperty)
    {
        sal_Int32 nIndex = pAllBorderWidthProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllBorderWidthProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllHeaderPaddingProperty)
    {
        sal_Int32 nIndex = pAllHeaderPaddingProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllHeaderPaddingProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllHeaderBorderProperty)
    {
        sal_Int32 nIndex = pAllHeaderBorderProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllHeaderBorderProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllHeaderBorderWidthProperty)
    {
        sal_Int32 nIndex = pAllHeaderBorderWidthProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllHeaderBorderWidthProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllFooterPaddingProperty)
    {
        sal_Int32 nIndex = pAllFooterPaddingProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllFooterPaddingProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllFooterBorderProperty)
    {
        sal_Int32 nIndex = pAllFooterBorderProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllFooterBorderProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pAllFooterBorderWidthProperty)
    {
        sal_Int32 nIndex = pAllFooterBorderWidthProperty->mnIndex + 2;
        XMLPropertyState aNewProperty (nIndex, pAllFooterBorderWidthProperty->maValue);
        for (sal_Int16 j = 0; j < 3; j++)
        {
            aNewProperty.mnIndex = nIndex++;
            rProperties.push_back(aNewProperty);
        }
    }
    if (pHeaderHeight)
    {
        sal_Bool bValue(sal_False);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        XMLPropertyState aNewProperty(pHeaderHeight->mnIndex + 2, aAny);
        rProperties.push_back(aNewProperty);
    }
    if (pHeaderMinHeight)
    {
        sal_Bool bValue(sal_True);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        XMLPropertyState aNewProperty(pHeaderMinHeight->mnIndex + 1, aAny);
        rProperties.push_back(aNewProperty);
    }
    if (pFooterHeight)
    {
        sal_Bool bValue(sal_False);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        XMLPropertyState aNewProperty(pFooterHeight->mnIndex + 2, aAny);
        rProperties.push_back(aNewProperty);
    }
    if (pFooterMinHeight)
    {
        sal_Bool bValue(sal_True);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        XMLPropertyState aNewProperty(pFooterMinHeight->mnIndex + 1, aAny);
        rProperties.push_back(aNewProperty);
    }
}

<commit_msg>increase the performance and merge the border with border_width<commit_after>/*************************************************************************
 *
 *  $RCSfile: PageMasterImportPropMapper.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: sab $ $Date: 2000-10-27 03:56:15 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _XMLOFF_PAGEMASTERIMPORTPROPMAPPER_HXX
#include "PageMasterImportPropMapper.hxx"
#endif
#ifndef _XMLOFF_PAGEMASTERPROPMAPPER_HXX
#include "PageMasterPropMapper.hxx"
#endif
#ifndef _XMLOFF_PAGEMASTERSTYLEMAP_HXX
#include "PageMasterStyleMap.hxx"
#endif

#ifndef _XMLOFF_PROPMAPPINGTYPES_HXX
#include "maptype.hxx"
#endif
#ifndef _COM_SUN_STAR_TABLE_BORDERLINE_HPP_
#include <com/sun/star/table/BorderLine.hpp>
#endif

#define XML_LINE_LEFT 0
#define XML_LINE_RIGHT 0
#define XML_LINE_TOP 0
#define XML_LINE_BOTTOM 0

using namespace ::com::sun::star;

PageMasterImportPropertyMapper::PageMasterImportPropertyMapper(
        const UniReference< XMLPropertySetMapper >& rMapper ) :
    SvXMLImportPropertyMapper( rMapper )
{
}

PageMasterImportPropertyMapper::~PageMasterImportPropertyMapper()
{
}

/*sal_Bool PageMasterImportPropertyMapper::handleSpecialItem(
        XMLPropertyState& rProperty,
        ::std::vector< XMLPropertyState >& rProperties,
        const ::rtl::OUString& rValue,
        const SvXMLUnitConverter& rUnitConverter,
        const SvXMLNamespaceMap& rNamespaceMap ) const
{
    return sal_True;
}*/

/*sal_Bool PageMasterImportPropertyMapper::handleNoItem(
        sal_Int32 nIndex,
        ::std::vector< XMLPropertyState >& rProperties,
        const ::rtl::OUString& rValue,
        const SvXMLUnitConverter& rUnitConverter,
        const SvXMLNamespaceMap& rNamespaceMap ) const
{
    return sal_True;
}*/

void PageMasterImportPropertyMapper::finished(::std::vector< XMLPropertyState >& rProperties, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
{
    SvXMLImportPropertyMapper::finished(rProperties, nStartIndex, nEndIndex);
    XMLPropertyState* pAllPaddingProperty = NULL;
    XMLPropertyState* pPadding[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pNewPadding[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllBorderProperty = NULL;
    XMLPropertyState* pBorders[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pNewBorders[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllBorderWidthProperty = NULL;
    XMLPropertyState* pBorderWidths[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllHeaderPaddingProperty = NULL;
    XMLPropertyState* pHeaderPadding[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pHeaderNewPadding[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllHeaderBorderProperty = NULL;
    XMLPropertyState* pHeaderBorders[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pHeaderNewBorders[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllHeaderBorderWidthProperty = NULL;
    XMLPropertyState* pHeaderBorderWidths[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllFooterPaddingProperty = NULL;
    XMLPropertyState* pFooterPadding[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pFooterNewPadding[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllFooterBorderProperty = NULL;
    XMLPropertyState* pFooterBorders[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pFooterNewBorders[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pAllFooterBorderWidthProperty = NULL;
    XMLPropertyState* pFooterBorderWidths[4] = { NULL, NULL, NULL, NULL };
    XMLPropertyState* pHeaderHeight = NULL;
    XMLPropertyState* pHeaderMinHeight = NULL;
    XMLPropertyState* pHeaderDynamic = NULL;
    XMLPropertyState* pFooterHeight = NULL;
    XMLPropertyState* pFooterMinHeight = NULL;
    XMLPropertyState* pFooterDynamic = NULL;
    ::std::vector< XMLPropertyState >::iterator property = rProperties.begin();
    for (property; property != rProperties.end(); property++)
    {
        sal_Int16 nContextID = getPropertySetMapper()->GetEntryContextId(property->mnIndex);
        if (property->mnIndex >= nStartIndex && property->mnIndex < nEndIndex)
        {
            switch (nContextID)
            {
                case CTF_PM_PADDINGALL                  : pAllPaddingProperty = property; break;
                case CTF_PM_PADDINGLEFT                 : pPadding[XML_LINE_LEFT] = property; break;
                case CTF_PM_PADDINGRIGHT                : pPadding[XML_LINE_RIGHT] = property; break;
                case CTF_PM_PADDINGTOP                  : pPadding[XML_LINE_TOP] = property; break;
                case CTF_PM_PADDINGBOTTOM               : pPadding[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_BORDERALL                   : pAllBorderProperty = property; break;
                case CTF_PM_BORDERLEFT                  : pBorders[XML_LINE_LEFT] = property; break;
                case CTF_PM_BORDERRIGHT                 : pBorders[XML_LINE_RIGHT] = property; break;
                case CTF_PM_BORDERTOP                   : pBorders[XML_LINE_TOP] = property; break;
                case CTF_PM_BORDERBOTTOM                : pBorders[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_BORDERWIDTHALL              : pAllBorderWidthProperty = property; break;
                case CTF_PM_BORDERWIDTHLEFT             : pBorderWidths[XML_LINE_LEFT] = property; break;
                case CTF_PM_BORDERWIDTHRIGHT            : pBorderWidths[XML_LINE_RIGHT] = property; break;
                case CTF_PM_BORDERWIDTHTOP              : pBorderWidths[XML_LINE_TOP] = property; break;
                case CTF_PM_BORDERWIDTHBOTTOM           : pBorderWidths[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_HEADERPADDINGALL            : pAllHeaderPaddingProperty = property; break;
                case CTF_PM_HEADERPADDINGLEFT           : pHeaderPadding[XML_LINE_LEFT] = property; break;
                case CTF_PM_HEADERPADDINGRIGHT          : pHeaderPadding[XML_LINE_RIGHT] = property; break;
                case CTF_PM_HEADERPADDINGTOP            : pHeaderPadding[XML_LINE_TOP] = property; break;
                case CTF_PM_HEADERPADDINGBOTTOM         : pHeaderPadding[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_HEADERBORDERALL             : pAllHeaderBorderProperty = property; break;
                case CTF_PM_HEADERBORDERLEFT            : pHeaderBorders[XML_LINE_LEFT] = property; break;
                case CTF_PM_HEADERBORDERRIGHT           : pHeaderBorders[XML_LINE_RIGHT] = property; break;
                case CTF_PM_HEADERBORDERTOP             : pHeaderBorders[XML_LINE_TOP] = property; break;
                case CTF_PM_HEADERBORDERBOTTOM          : pHeaderBorders[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_HEADERBORDERWIDTHALL        : pAllHeaderBorderWidthProperty = property; break;
                case CTF_PM_HEADERBORDERWIDTHLEFT       : pHeaderBorderWidths[XML_LINE_LEFT] = property; break;
                case CTF_PM_HEADERBORDERWIDTHRIGHT      : pHeaderBorderWidths[XML_LINE_RIGHT] = property; break;
                case CTF_PM_HEADERBORDERWIDTHTOP        : pHeaderBorderWidths[XML_LINE_TOP] = property; break;
                case CTF_PM_HEADERBORDERWIDTHBOTTOM     : pHeaderBorderWidths[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_FOOTERPADDINGALL            : pAllFooterPaddingProperty = property; break;
                case CTF_PM_FOOTERPADDINGLEFT           : pFooterPadding[XML_LINE_LEFT] = property; break;
                case CTF_PM_FOOTERPADDINGRIGHT          : pFooterPadding[XML_LINE_RIGHT] = property; break;
                case CTF_PM_FOOTERPADDINGTOP            : pFooterPadding[XML_LINE_TOP] = property; break;
                case CTF_PM_FOOTERPADDINGBOTTOM         : pFooterPadding[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_FOOTERBORDERALL             : pAllFooterBorderProperty = property; break;
                case CTF_PM_FOOTERBORDERLEFT            : pFooterBorders[XML_LINE_LEFT] = property; break;
                case CTF_PM_FOOTERBORDERRIGHT           : pFooterBorders[XML_LINE_RIGHT] = property; break;
                case CTF_PM_FOOTERBORDERTOP             : pFooterBorders[XML_LINE_TOP] = property; break;
                case CTF_PM_FOOTERBORDERBOTTOM          : pFooterBorders[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_FOOTERBORDERWIDTHALL        : pAllFooterBorderWidthProperty = property; break;
                case CTF_PM_FOOTERBORDERWIDTHLEFT       : pFooterBorderWidths[XML_LINE_LEFT] = property; break;
                case CTF_PM_FOOTERBORDERWIDTHRIGHT      : pFooterBorderWidths[XML_LINE_RIGHT] = property; break;
                case CTF_PM_FOOTERBORDERWIDTHTOP        : pFooterBorderWidths[XML_LINE_TOP] = property; break;
                case CTF_PM_FOOTERBORDERWIDTHBOTTOM     : pFooterBorderWidths[XML_LINE_BOTTOM] = property; break;
                case CTF_PM_HEADERHEIGHT                : pHeaderHeight = property; break;
                case CTF_PM_HEADERMINHEIGHT             : pHeaderMinHeight = property; break;
                case CTF_PM_FOOTERHEIGHT                : pFooterHeight = property; break;
                case CTF_PM_FOOTERMINHEIGHT             : pFooterMinHeight = property; break;
            }
        }
    }

    for (sal_uInt16 i = 0; i < 4; i++)
    {
        if (pAllPaddingProperty && !pPadding[i])
            pNewPadding[i] = new XMLPropertyState(pAllPaddingProperty->mnIndex + 1 + i, pAllPaddingProperty->maValue);
        if (pAllBorderProperty && !pBorders[i])
        {
            pNewBorders[i] = new XMLPropertyState(pAllBorderProperty->mnIndex + 1 + i, pAllBorderProperty->maValue);
            pBorders[i] = pNewBorders[i];
        }
        if( !pBorderWidths[i] )
            pBorderWidths[i] = pAllBorderWidthProperty;
        else
            pBorderWidths[i]->mnIndex = -1;
        if( pBorders[i] )
        {
            table::BorderLine aBorderLine;
            pBorders[i]->maValue >>= aBorderLine;
             if( pBorderWidths[i] )
            {
                table::BorderLine aBorderLineWidth;
                pBorderWidths[i]->maValue >>= aBorderLineWidth;
                aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
                aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
                aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
                pBorders[i]->maValue <<= aBorderLine;
            }
        }
        if (pAllHeaderPaddingProperty && !pHeaderPadding[i])
            pHeaderNewPadding[i] = new XMLPropertyState(pAllHeaderPaddingProperty->mnIndex + 1 + i, pAllHeaderPaddingProperty->maValue);
        if (pAllHeaderBorderProperty && !pHeaderBorders[i])
            pHeaderNewBorders[i] = new XMLPropertyState(pAllHeaderBorderProperty->mnIndex + 1 + i, pAllHeaderBorderProperty->maValue);
        if( !pHeaderBorderWidths[i] )
            pHeaderBorderWidths[i] = pAllHeaderBorderWidthProperty;
        else
            pHeaderBorderWidths[i]->mnIndex = -1;
        if( pHeaderBorders[i] )
        {
            table::BorderLine aBorderLine;
            pHeaderBorders[i]->maValue >>= aBorderLine;
             if( pHeaderBorderWidths[i] )
            {
                table::BorderLine aBorderLineWidth;
                pHeaderBorderWidths[i]->maValue >>= aBorderLineWidth;
                aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
                aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
                aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
                pHeaderBorders[i]->maValue <<= aBorderLine;
            }
        }
        if (pAllFooterPaddingProperty && !pFooterPadding[i])
            pFooterNewPadding[i] = new XMLPropertyState(pAllFooterPaddingProperty->mnIndex + 1 + i, pAllFooterPaddingProperty->maValue);
        if (pAllFooterBorderProperty && !pFooterBorders[i])
            pFooterNewBorders[i] = new XMLPropertyState(pAllFooterBorderProperty->mnIndex + 1 + i, pAllFooterBorderProperty->maValue);
        if( !pFooterBorderWidths[i] )
            pFooterBorderWidths[i] = pAllFooterBorderWidthProperty;
        else
            pFooterBorderWidths[i]->mnIndex = -1;
        if( pFooterBorders[i] )
        {
            table::BorderLine aBorderLine;
            pFooterBorders[i]->maValue >>= aBorderLine;
             if( pFooterBorderWidths[i] )
            {
                table::BorderLine aBorderLineWidth;
                pFooterBorderWidths[i]->maValue >>= aBorderLineWidth;
                aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
                aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
                aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
                pFooterBorders[i]->maValue <<= aBorderLine;
            }
        }
    }

    if (pHeaderHeight)
    {
        sal_Bool bValue(sal_False);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        pHeaderDynamic = new XMLPropertyState(pHeaderHeight->mnIndex + 2, aAny);
    }
    if (pHeaderMinHeight)
    {
        sal_Bool bValue(sal_True);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        pHeaderDynamic = new XMLPropertyState(pHeaderMinHeight->mnIndex + 1, aAny);
    }
    if (pFooterHeight)
    {
        sal_Bool bValue(sal_False);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        pFooterDynamic = new XMLPropertyState(pFooterHeight->mnIndex + 2, aAny);
    }
    if (pFooterMinHeight)
    {
        sal_Bool bValue(sal_True);
        uno::Any aAny;
        aAny.setValue( &bValue, ::getBooleanCppuType() );
        pFooterDynamic = new XMLPropertyState(pFooterMinHeight->mnIndex + 1, aAny);
    }
    for (i = 0; i < 4; i++)
    {
        if (pNewPadding[i])
        {
            rProperties.push_back(*pNewPadding[i]);
            delete pNewPadding[i];
        }
        if (pNewBorders[i])
        {
            rProperties.push_back(*pNewBorders[i]);
            delete pNewBorders[i];
        }
        if (pHeaderNewPadding[i])
        {
            rProperties.push_back(*pHeaderNewPadding[i]);
            delete pHeaderNewPadding[i];
        }
        if (pHeaderNewBorders[i])
        {
            rProperties.push_back(*pHeaderNewBorders[i]);
            delete pHeaderNewBorders[i];
        }
        if (pFooterNewPadding[i])
        {
            rProperties.push_back(*pFooterNewPadding[i]);
            delete pFooterNewPadding[i];
        }
        if (pFooterNewBorders[i])
        {
            rProperties.push_back(*pFooterNewBorders[i]);
            delete pFooterNewBorders[i];
        }
    }
    if(pHeaderDynamic)
    {
        rProperties.push_back(*pHeaderDynamic);
        delete pHeaderDynamic;
    }
    if(pFooterDynamic)
    {
        rProperties.push_back(*pFooterDynamic);
        delete pFooterDynamic;
    }
}

<|endoftext|>


<commit_before>//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the MSP430 target.
//
//===----------------------------------------------------------------------===//

#include "MSP430.h"
#include "MSP430ISelLowering.h"
#include "MSP430TargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include <queue>
#include <set>
using namespace llvm;

/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
/// instructions for SelectionDAG operations.
///
namespace {
  class MSP430DAGToDAGISel : public SelectionDAGISel {
    MSP430TargetLowering &Lowering;
    const MSP430Subtarget &Subtarget;

  public:
    MSP430DAGToDAGISel(MSP430TargetMachine &TM)
      : SelectionDAGISel(TM),
        Lowering(*TM.getTargetLowering()),
        Subtarget(*TM.getSubtargetImpl()) { }

    virtual void InstructionSelect();

    virtual const char *getPassName() const {
      return "MSP430 DAG->DAG Pattern Instruction Selection";
    }

    // Include the pieces autogenerated from the target description.
  #include "MSP430GenDAGISel.inc"

  private:
    SDNode *Select(SDValue Op);
  };
}  // end anonymous namespace

/// createMSP430ISelDag - This pass converts a legalized DAG into a
/// MSP430-specific DAG, ready for instruction scheduling.
///
FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM) {
  return new MSP430DAGToDAGISel(TM);
}

/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MSP430DAGToDAGISel::
InstructionSelect() {
  DEBUG(BB->dump());

  // Select target instructions for the DAG.
  SelectRoot(*CurDAG);

  CurDAG->RemoveDeadNodes();
}

SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
  return SelectCode(Op);
}
<commit_msg>Cleanup<commit_after>//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the MSP430 target.
//
//===----------------------------------------------------------------------===//

#include "MSP430.h"
#include "MSP430ISelLowering.h"
#include "MSP430TargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include <queue>
#include <set>
using namespace llvm;

/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
/// instructions for SelectionDAG operations.
///
namespace {
  class MSP430DAGToDAGISel : public SelectionDAGISel {
    MSP430TargetLowering &Lowering;
    const MSP430Subtarget &Subtarget;

  public:
    MSP430DAGToDAGISel(MSP430TargetMachine &TM)
      : SelectionDAGISel(TM),
        Lowering(*TM.getTargetLowering()),
        Subtarget(*TM.getSubtargetImpl()) { }

    virtual void InstructionSelect();

    virtual const char *getPassName() const {
      return "MSP430 DAG->DAG Pattern Instruction Selection";
    }

    // Include the pieces autogenerated from the target description.
  #include "MSP430GenDAGISel.inc"

  private:
    SDNode *Select(SDValue Op);
  };
}  // end anonymous namespace

/// createMSP430ISelDag - This pass converts a legalized DAG into a
/// MSP430-specific DAG, ready for instruction scheduling.
///
FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM) {
  return new MSP430DAGToDAGISel(TM);
}

/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MSP430DAGToDAGISel::InstructionSelect() {
  DEBUG(BB->dump());

  // Select target instructions for the DAG.
  SelectRoot(*CurDAG);

  CurDAG->RemoveDeadNodes();
}

SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
  return SelectCode(Op);
}
<|endoftext|>


<commit_before>//===-- SystemZLongBranch.cpp - Branch lengthening for SystemZ ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass makes sure that all branches are in range.  There are several ways
// in which this could be done.  One aggressive approach is to assume that all
// branches are in range and successively replace those that turn out not
// to be in range with a longer form (branch relaxation).  A simple
// implementation is to continually walk through the function relaxing
// branches until no more changes are needed and a fixed point is reached.
// However, in the pathological worst case, this implementation is
// quadratic in the number of blocks; relaxing branch N can make branch N-1
// go out of range, which in turn can make branch N-2 go out of range,
// and so on.
//
// An alternative approach is to assume that all branches must be
// converted to their long forms, then reinstate the short forms of
// branches that, even under this pessimistic assumption, turn out to be
// in range (branch shortening).  This too can be implemented as a function
// walk that is repeated until a fixed point is reached.  In general,
// the result of shortening is not as good as that of relaxation, and
// shortening is also quadratic in the worst case; shortening branch N
// can bring branch N-1 in range of the short form, which in turn can do
// the same for branch N-2, and so on.  The main advantage of shortening
// is that each walk through the function produces valid code, so it is
// possible to stop at any point after the first walk.  The quadraticness
// could therefore be handled with a maximum pass count, although the
// question then becomes: what maximum count should be used?
//
// On SystemZ, long branches are only needed for functions bigger than 64k,
// which are relatively rare to begin with, and the long branch sequences
// are actually relatively cheap.  It therefore doesn't seem worth spending
// much compilation time on the problem.  Instead, the approach we take is:
//
// (1) Check whether all branches can be short (the usual case).  Exit the
//     pass if so.
// (2) If one branch needs to be long, work out the address that each block
//     would have if all branches need to be long, as for shortening above.
// (3) Relax any branch that is out of range according to this pessimistic
//     assumption.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "systemz-long-branch"

#include "SystemZTargetMachine.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"

using namespace llvm;

STATISTIC(LongBranches, "Number of long branches.");

namespace {
  typedef MachineBasicBlock::iterator Iter;

  // Represents positional information about a basic block.
  struct MBBInfo {
    // The address that we currently assume the block has, relative to
    // the start of the function.  This is designed so that taking the
    // difference between two addresses gives a conservative upper bound
    // on the distance between them.
    uint64_t Address;

    // The size of the block in bytes, excluding terminators.
    // This value never changes.
    uint64_t Size;

    // The minimum alignment of the block, as a log2 value.
    // This value never changes.
    unsigned Alignment;

    // The number of terminators in this block.  This value never changes.
    unsigned NumTerminators;

    MBBInfo()
      : Address(0), Size(0), Alignment(0), NumTerminators(0) {}
  };

  // Represents the state of a block terminator.
  struct TerminatorInfo {
    // If this terminator is a relaxable branch, this points to the branch
    // instruction, otherwise it is null.
    MachineInstr *Branch;

    // The current address of the terminator, in the same form as
    // for BlockInfo.
    uint64_t Address;

    // The current size of the terminator in bytes.
    uint64_t Size;

    // If Branch is nonnull, this is the number of the target block,
    // otherwise it is unused.
    unsigned TargetBlock;

    // If Branch is nonnull, this is the length of the longest relaxed form,
    // otherwise it is zero.
    unsigned ExtraRelaxSize;

    TerminatorInfo() : Branch(0), Size(0), TargetBlock(0), ExtraRelaxSize(0) {}
  };

  // Used to keep track of the current position while iterating over the blocks.
  struct BlockPosition {
    // The offset from the start of the function, in the same form
    // as BlockInfo.
    uint64_t Address;

    // The number of low bits in Address that are known to be the same
    // as the runtime address.
    unsigned KnownBits;

    BlockPosition(unsigned InitialAlignment)
      : Address(0), KnownBits(InitialAlignment) {}
  };

  class SystemZLongBranch : public MachineFunctionPass {
  public:
    static char ID;
    SystemZLongBranch(const SystemZTargetMachine &tm)
      : MachineFunctionPass(ID),
        TII(static_cast<const SystemZInstrInfo *>(tm.getInstrInfo())) {}

    virtual const char *getPassName() const {
      return "SystemZ Long Branch";
    }

    bool runOnMachineFunction(MachineFunction &F);

  private:
    void skipNonTerminators(BlockPosition &Position, MBBInfo &Block);
    void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
                        bool AssumeRelaxed);
    TerminatorInfo describeTerminator(MachineInstr *MI);
    uint64_t initMBBInfo();
    bool mustRelaxBranch(const TerminatorInfo &Terminator);
    bool mustRelaxABranch();
    void setWorstCaseAddresses();
    void relaxBranch(TerminatorInfo &Terminator);
    void relaxBranches();

    const SystemZInstrInfo *TII;
    MachineFunction *MF;
    SmallVector<MBBInfo, 16> MBBs;
    SmallVector<TerminatorInfo, 16> Terminators;
  };

  char SystemZLongBranch::ID = 0;

  const uint64_t MaxBackwardRange = 0x10000;
  const uint64_t MaxForwardRange = 0xfffe;
} // end of anonymous namespace

FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) {
  return new SystemZLongBranch(TM);
}

// Position describes the state immediately before Block.  Update Block
// accordingly and move Position to the end of the block's non-terminator
// instructions.
void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
                                           MBBInfo &Block) {
  if (Block.Alignment > Position.KnownBits) {
    // When calculating the address of Block, we need to conservatively
    // assume that Block had the worst possible misalignment.
    Position.Address += ((uint64_t(1) << Block.Alignment) -
                         (uint64_t(1) << Position.KnownBits));
    Position.KnownBits = Block.Alignment;
  }

  // Align the addresses.
  uint64_t AlignMask = (uint64_t(1) << Block.Alignment) - 1;
  Position.Address = (Position.Address + AlignMask) & ~AlignMask;

  // Record the block's position.
  Block.Address = Position.Address;

  // Move past the non-terminators in the block.
  Position.Address += Block.Size;
}

// Position describes the state immediately before Terminator.
// Update Terminator accordingly and move Position past it.
// Assume that Terminator will be relaxed if AssumeRelaxed.
void SystemZLongBranch::skipTerminator(BlockPosition &Position,
                                       TerminatorInfo &Terminator,
                                       bool AssumeRelaxed) {
  Terminator.Address = Position.Address;
  Position.Address += Terminator.Size;
  if (AssumeRelaxed)
    Position.Address += Terminator.ExtraRelaxSize;
}

// Return a description of terminator instruction MI.
TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr *MI) {
  TerminatorInfo Terminator;
  Terminator.Size = TII->getInstSizeInBytes(MI);
  if (MI->isConditionalBranch() || MI->isUnconditionalBranch()) {
    Terminator.Branch = MI;
    switch (MI->getOpcode()) {
    case SystemZ::J:
      // Relaxes to JG, which is 2 bytes longer.
      Terminator.TargetBlock = MI->getOperand(0).getMBB()->getNumber();
      Terminator.ExtraRelaxSize = 2;
      break;
    case SystemZ::BRC:
      // Relaxes to BRCL, which is 2 bytes longer.  Operand 0 is the
      // condition code mask.
      Terminator.TargetBlock = MI->getOperand(1).getMBB()->getNumber();
      Terminator.ExtraRelaxSize = 2;
      break;
    default:
      llvm_unreachable("Unrecognized branch instruction");
    }
  }
  return Terminator;
}

// Fill MBBs and Terminators, setting the addresses on the assumption
// that no branches need relaxation.  Return the size of the function under
// this assumption.
uint64_t SystemZLongBranch::initMBBInfo() {
  MF->RenumberBlocks();
  unsigned NumBlocks = MF->size();

  MBBs.clear();
  MBBs.resize(NumBlocks);

  Terminators.clear();
  Terminators.reserve(NumBlocks);

  BlockPosition Position(MF->getAlignment());
  for (unsigned I = 0; I < NumBlocks; ++I) {
    MachineBasicBlock *MBB = MF->getBlockNumbered(I);
    MBBInfo &Block = MBBs[I];

    // Record the alignment, for quick access.
    Block.Alignment = MBB->getAlignment();

    // Calculate the size of the fixed part of the block.
    MachineBasicBlock::iterator MI = MBB->begin();
    MachineBasicBlock::iterator End = MBB->end();
    while (MI != End && !MI->isTerminator()) {
      Block.Size += TII->getInstSizeInBytes(MI);
      ++MI;
    }
    skipNonTerminators(Position, Block);

    // Add the terminators.
    while (MI != End) {
      if (!MI->isDebugValue()) {
        assert(MI->isTerminator() && "Terminator followed by non-terminator");
        Terminators.push_back(describeTerminator(MI));
        skipTerminator(Position, Terminators.back(), false);
        ++Block.NumTerminators;
      }
      ++MI;
    }
  }

  return Position.Address;
}

// Return true if, under current assumptions, Terminator needs to be relaxed.
bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator) {
  if (!Terminator.Branch)
    return false;

  const MBBInfo &Target = MBBs[Terminator.TargetBlock];
  if (Target.Address < Terminator.Address) {
    if (Terminator.Address - Target.Address <= MaxBackwardRange)
      return false;
  } else {
    if (Target.Address - Terminator.Address <= MaxForwardRange)
      return false;
  }

  return true;
}

// Return true if, under current assumptions, any terminator needs
// to be relaxed.
bool SystemZLongBranch::mustRelaxABranch() {
  for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
         TE = Terminators.end(); TI != TE; ++TI)
    if (mustRelaxBranch(*TI))
      return true;
  return false;
}

// Set the address of each block on the assumption that all branches
// must be long.
void SystemZLongBranch::setWorstCaseAddresses() {
  SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
  BlockPosition Position(MF->getAlignment());
  for (SmallVector<MBBInfo, 16>::iterator BI = MBBs.begin(), BE = MBBs.end();
       BI != BE; ++BI) {
    skipNonTerminators(Position, *BI);
    for (unsigned BTI = 0, BTE = BI->NumTerminators; BTI != BTE; ++BTI) {
      skipTerminator(Position, *TI, true);
      ++TI;
    }
  }
}

// Relax the branch described by Terminator.
void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
  MachineInstr *Branch = Terminator.Branch;
  switch (Branch->getOpcode()) {
    case SystemZ::J:
      Branch->setDesc(TII->get(SystemZ::JG));
      break;
    case SystemZ::BRC:
      Branch->setDesc(TII->get(SystemZ::BRCL));
      break;
    default:
      llvm_unreachable("Unrecognized branch");
    }

  Terminator.Size += Terminator.ExtraRelaxSize;
  Terminator.ExtraRelaxSize = 0;
  Terminator.Branch = 0;

  ++LongBranches;
}

// Relax any branches that need to be relaxed, under current assumptions.
void SystemZLongBranch::relaxBranches() {
  for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
         TE = Terminators.end(); TI != TE; ++TI)
    if (mustRelaxBranch(*TI))
      relaxBranch(*TI);
}

bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {
  MF = &F;
  uint64_t Size = initMBBInfo();
  if (Size <= MaxForwardRange || !mustRelaxABranch())
    return false;

  setWorstCaseAddresses();
  relaxBranches();
  return true;
}
<commit_msg>Fix indentation<commit_after>//===-- SystemZLongBranch.cpp - Branch lengthening for SystemZ ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass makes sure that all branches are in range.  There are several ways
// in which this could be done.  One aggressive approach is to assume that all
// branches are in range and successively replace those that turn out not
// to be in range with a longer form (branch relaxation).  A simple
// implementation is to continually walk through the function relaxing
// branches until no more changes are needed and a fixed point is reached.
// However, in the pathological worst case, this implementation is
// quadratic in the number of blocks; relaxing branch N can make branch N-1
// go out of range, which in turn can make branch N-2 go out of range,
// and so on.
//
// An alternative approach is to assume that all branches must be
// converted to their long forms, then reinstate the short forms of
// branches that, even under this pessimistic assumption, turn out to be
// in range (branch shortening).  This too can be implemented as a function
// walk that is repeated until a fixed point is reached.  In general,
// the result of shortening is not as good as that of relaxation, and
// shortening is also quadratic in the worst case; shortening branch N
// can bring branch N-1 in range of the short form, which in turn can do
// the same for branch N-2, and so on.  The main advantage of shortening
// is that each walk through the function produces valid code, so it is
// possible to stop at any point after the first walk.  The quadraticness
// could therefore be handled with a maximum pass count, although the
// question then becomes: what maximum count should be used?
//
// On SystemZ, long branches are only needed for functions bigger than 64k,
// which are relatively rare to begin with, and the long branch sequences
// are actually relatively cheap.  It therefore doesn't seem worth spending
// much compilation time on the problem.  Instead, the approach we take is:
//
// (1) Check whether all branches can be short (the usual case).  Exit the
//     pass if so.
// (2) If one branch needs to be long, work out the address that each block
//     would have if all branches need to be long, as for shortening above.
// (3) Relax any branch that is out of range according to this pessimistic
//     assumption.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "systemz-long-branch"

#include "SystemZTargetMachine.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"

using namespace llvm;

STATISTIC(LongBranches, "Number of long branches.");

namespace {
  typedef MachineBasicBlock::iterator Iter;

  // Represents positional information about a basic block.
  struct MBBInfo {
    // The address that we currently assume the block has, relative to
    // the start of the function.  This is designed so that taking the
    // difference between two addresses gives a conservative upper bound
    // on the distance between them.
    uint64_t Address;

    // The size of the block in bytes, excluding terminators.
    // This value never changes.
    uint64_t Size;

    // The minimum alignment of the block, as a log2 value.
    // This value never changes.
    unsigned Alignment;

    // The number of terminators in this block.  This value never changes.
    unsigned NumTerminators;

    MBBInfo()
      : Address(0), Size(0), Alignment(0), NumTerminators(0) {}
  };

  // Represents the state of a block terminator.
  struct TerminatorInfo {
    // If this terminator is a relaxable branch, this points to the branch
    // instruction, otherwise it is null.
    MachineInstr *Branch;

    // The current address of the terminator, in the same form as
    // for BlockInfo.
    uint64_t Address;

    // The current size of the terminator in bytes.
    uint64_t Size;

    // If Branch is nonnull, this is the number of the target block,
    // otherwise it is unused.
    unsigned TargetBlock;

    // If Branch is nonnull, this is the length of the longest relaxed form,
    // otherwise it is zero.
    unsigned ExtraRelaxSize;

    TerminatorInfo() : Branch(0), Size(0), TargetBlock(0), ExtraRelaxSize(0) {}
  };

  // Used to keep track of the current position while iterating over the blocks.
  struct BlockPosition {
    // The offset from the start of the function, in the same form
    // as BlockInfo.
    uint64_t Address;

    // The number of low bits in Address that are known to be the same
    // as the runtime address.
    unsigned KnownBits;

    BlockPosition(unsigned InitialAlignment)
      : Address(0), KnownBits(InitialAlignment) {}
  };

  class SystemZLongBranch : public MachineFunctionPass {
  public:
    static char ID;
    SystemZLongBranch(const SystemZTargetMachine &tm)
      : MachineFunctionPass(ID),
        TII(static_cast<const SystemZInstrInfo *>(tm.getInstrInfo())) {}

    virtual const char *getPassName() const {
      return "SystemZ Long Branch";
    }

    bool runOnMachineFunction(MachineFunction &F);

  private:
    void skipNonTerminators(BlockPosition &Position, MBBInfo &Block);
    void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
                        bool AssumeRelaxed);
    TerminatorInfo describeTerminator(MachineInstr *MI);
    uint64_t initMBBInfo();
    bool mustRelaxBranch(const TerminatorInfo &Terminator);
    bool mustRelaxABranch();
    void setWorstCaseAddresses();
    void relaxBranch(TerminatorInfo &Terminator);
    void relaxBranches();

    const SystemZInstrInfo *TII;
    MachineFunction *MF;
    SmallVector<MBBInfo, 16> MBBs;
    SmallVector<TerminatorInfo, 16> Terminators;
  };

  char SystemZLongBranch::ID = 0;

  const uint64_t MaxBackwardRange = 0x10000;
  const uint64_t MaxForwardRange = 0xfffe;
} // end of anonymous namespace

FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) {
  return new SystemZLongBranch(TM);
}

// Position describes the state immediately before Block.  Update Block
// accordingly and move Position to the end of the block's non-terminator
// instructions.
void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
                                           MBBInfo &Block) {
  if (Block.Alignment > Position.KnownBits) {
    // When calculating the address of Block, we need to conservatively
    // assume that Block had the worst possible misalignment.
    Position.Address += ((uint64_t(1) << Block.Alignment) -
                         (uint64_t(1) << Position.KnownBits));
    Position.KnownBits = Block.Alignment;
  }

  // Align the addresses.
  uint64_t AlignMask = (uint64_t(1) << Block.Alignment) - 1;
  Position.Address = (Position.Address + AlignMask) & ~AlignMask;

  // Record the block's position.
  Block.Address = Position.Address;

  // Move past the non-terminators in the block.
  Position.Address += Block.Size;
}

// Position describes the state immediately before Terminator.
// Update Terminator accordingly and move Position past it.
// Assume that Terminator will be relaxed if AssumeRelaxed.
void SystemZLongBranch::skipTerminator(BlockPosition &Position,
                                       TerminatorInfo &Terminator,
                                       bool AssumeRelaxed) {
  Terminator.Address = Position.Address;
  Position.Address += Terminator.Size;
  if (AssumeRelaxed)
    Position.Address += Terminator.ExtraRelaxSize;
}

// Return a description of terminator instruction MI.
TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr *MI) {
  TerminatorInfo Terminator;
  Terminator.Size = TII->getInstSizeInBytes(MI);
  if (MI->isConditionalBranch() || MI->isUnconditionalBranch()) {
    Terminator.Branch = MI;
    switch (MI->getOpcode()) {
    case SystemZ::J:
      // Relaxes to JG, which is 2 bytes longer.
      Terminator.TargetBlock = MI->getOperand(0).getMBB()->getNumber();
      Terminator.ExtraRelaxSize = 2;
      break;
    case SystemZ::BRC:
      // Relaxes to BRCL, which is 2 bytes longer.  Operand 0 is the
      // condition code mask.
      Terminator.TargetBlock = MI->getOperand(1).getMBB()->getNumber();
      Terminator.ExtraRelaxSize = 2;
      break;
    default:
      llvm_unreachable("Unrecognized branch instruction");
    }
  }
  return Terminator;
}

// Fill MBBs and Terminators, setting the addresses on the assumption
// that no branches need relaxation.  Return the size of the function under
// this assumption.
uint64_t SystemZLongBranch::initMBBInfo() {
  MF->RenumberBlocks();
  unsigned NumBlocks = MF->size();

  MBBs.clear();
  MBBs.resize(NumBlocks);

  Terminators.clear();
  Terminators.reserve(NumBlocks);

  BlockPosition Position(MF->getAlignment());
  for (unsigned I = 0; I < NumBlocks; ++I) {
    MachineBasicBlock *MBB = MF->getBlockNumbered(I);
    MBBInfo &Block = MBBs[I];

    // Record the alignment, for quick access.
    Block.Alignment = MBB->getAlignment();

    // Calculate the size of the fixed part of the block.
    MachineBasicBlock::iterator MI = MBB->begin();
    MachineBasicBlock::iterator End = MBB->end();
    while (MI != End && !MI->isTerminator()) {
      Block.Size += TII->getInstSizeInBytes(MI);
      ++MI;
    }
    skipNonTerminators(Position, Block);

    // Add the terminators.
    while (MI != End) {
      if (!MI->isDebugValue()) {
        assert(MI->isTerminator() && "Terminator followed by non-terminator");
        Terminators.push_back(describeTerminator(MI));
        skipTerminator(Position, Terminators.back(), false);
        ++Block.NumTerminators;
      }
      ++MI;
    }
  }

  return Position.Address;
}

// Return true if, under current assumptions, Terminator needs to be relaxed.
bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator) {
  if (!Terminator.Branch)
    return false;

  const MBBInfo &Target = MBBs[Terminator.TargetBlock];
  if (Target.Address < Terminator.Address) {
    if (Terminator.Address - Target.Address <= MaxBackwardRange)
      return false;
  } else {
    if (Target.Address - Terminator.Address <= MaxForwardRange)
      return false;
  }

  return true;
}

// Return true if, under current assumptions, any terminator needs
// to be relaxed.
bool SystemZLongBranch::mustRelaxABranch() {
  for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
         TE = Terminators.end(); TI != TE; ++TI)
    if (mustRelaxBranch(*TI))
      return true;
  return false;
}

// Set the address of each block on the assumption that all branches
// must be long.
void SystemZLongBranch::setWorstCaseAddresses() {
  SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
  BlockPosition Position(MF->getAlignment());
  for (SmallVector<MBBInfo, 16>::iterator BI = MBBs.begin(), BE = MBBs.end();
       BI != BE; ++BI) {
    skipNonTerminators(Position, *BI);
    for (unsigned BTI = 0, BTE = BI->NumTerminators; BTI != BTE; ++BTI) {
      skipTerminator(Position, *TI, true);
      ++TI;
    }
  }
}

// Relax the branch described by Terminator.
void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
  MachineInstr *Branch = Terminator.Branch;
  switch (Branch->getOpcode()) {
  case SystemZ::J:
    Branch->setDesc(TII->get(SystemZ::JG));
    break;
  case SystemZ::BRC:
    Branch->setDesc(TII->get(SystemZ::BRCL));
    break;
  default:
    llvm_unreachable("Unrecognized branch");
  }

  Terminator.Size += Terminator.ExtraRelaxSize;
  Terminator.ExtraRelaxSize = 0;
  Terminator.Branch = 0;

  ++LongBranches;
}

// Relax any branches that need to be relaxed, under current assumptions.
void SystemZLongBranch::relaxBranches() {
  for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
         TE = Terminators.end(); TI != TE; ++TI)
    if (mustRelaxBranch(*TI))
      relaxBranch(*TI);
}

bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {
  MF = &F;
  uint64_t Size = initMBBInfo();
  if (Size <= MaxForwardRange || !mustRelaxABranch())
    return false;

  setWorstCaseAddresses();
  relaxBranches();
  return true;
}
<|endoftext|>


<commit_before>//===-- ArgumentPromotion.cpp - Promote 'by reference' arguments ----------===//
//
//                     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 pass promotes "by reference" arguments to be "by value" arguments.  In
// practice, this means looking for internal functions that have pointer
// arguments.  If we can prove, through the use of alias analysis, that that an
// argument is *only* loaded, then we can pass the value into the function
// instead of the address of the value.  This can cause recursive simplification
// of code, and lead to the elimination of allocas, especially in C++ template
// code like the STL.
//
// Note that this transformation could also be done for arguments that are only
// stored to (returning the value instead), but we do not currently handle that
// case.
//
// Note that we should be able to promote pointers to structures that are only
// loaded from as well.  The danger is creating way to many arguments, so this
// transformation should be limited to 3 element structs or something.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
#include "Support/Debug.h"
#include "Support/DepthFirstIterator.h"
#include "Support/Statistic.h"
#include <set>
using namespace llvm;

namespace {
  Statistic<> NumArgumentsPromoted("argpromotion",
                                   "Number of pointer arguments promoted");
  Statistic<> NumArgumentsDead("argpromotion",
                               "Number of dead pointer args eliminated");

  /// ArgPromotion - The 'by reference' to 'by value' argument promotion pass.
  ///
  class ArgPromotion : public Pass {
    // WorkList - The set of internal functions that we have yet to process.  As
    // we eliminate arguments from a function, we push all callers into this set
    // so that the by reference argument can be bubbled out as far as possible.
    // This set contains only internal functions.
    std::set<Function*> WorkList;
  public:
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<AliasAnalysis>();
      AU.addRequired<TargetData>();
    }

    virtual bool run(Module &M);
  private:
    bool PromoteArguments(Function *F);
    bool isSafeToPromoteArgument(Argument *Arg) const;
    void DoPromotion(Function *F, std::vector<Argument*> &ArgsToPromote);
  };

  RegisterOpt<ArgPromotion> X("argpromotion",
                              "Promote 'by reference' arguments to scalars");
}

Pass *llvm::createArgumentPromotionPass() {
  return new ArgPromotion();
}

bool ArgPromotion::run(Module &M) {
  bool Changed = false;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (I->hasInternalLinkage()) {
      WorkList.insert(I);

      // If there are any constant pointer refs pointing to this function,
      // eliminate them now if possible.
      ConstantPointerRef *CPR = 0;
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI)
        if ((CPR = dyn_cast<ConstantPointerRef>(*UI)))
          break;  // Found one!
      if (CPR) {
        // See if we can transform all users to use the function directly.
        while (!CPR->use_empty()) {
          User *TheUser = CPR->use_back();
          if (!isa<Constant>(TheUser) && !isa<GlobalVariable>(TheUser)) {
            Changed = true;
            TheUser->replaceUsesOfWith(CPR, I);
          } else {
            // We won't be able to eliminate all users.  :(
            WorkList.erase(I);  // Minor efficiency win.
            break;
          }
        }

        // If we nuked all users of the CPR, kill the CPR now!
        if (CPR->use_empty()) {
          CPR->destroyConstant();
          Changed = true;
        }
      }
    }

  while (!WorkList.empty()) {
    Function *F = *WorkList.begin();
    WorkList.erase(WorkList.begin());

    if (PromoteArguments(F))    // Attempt to promote an argument.
      Changed = true;           // Remember that we changed something.
  }

  return Changed;
}

bool ArgPromotion::PromoteArguments(Function *F) {
  assert(F->hasInternalLinkage() && "We can only process internal functions!");

  // First check: see if there are any pointer arguments!  If not, quick exit.
  std::vector<Argument*> PointerArgs;
  for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I)
    if (isa<PointerType>(I->getType()))
      PointerArgs.push_back(I);
  if (PointerArgs.empty()) return false;

  // Second check: make sure that all callers are direct callers.  We can't
  // transform functions that have indirect callers.
  for (Value::use_iterator UI = F->use_begin(), E = F->use_end();
       UI != E; ++UI)
    // What about CPRs?
    if (!CallSite::get(*UI).getInstruction())
      return false;  // Cannot promote an indirect call!

  // Check to see which arguments are promotable.  If an argument is not
  // promotable, remove it from the PointerArgs vector.
  for (unsigned i = 0; i != PointerArgs.size(); ++i)
    if (!isSafeToPromoteArgument(PointerArgs[i])) {
      std::swap(PointerArgs[i--], PointerArgs.back());
      PointerArgs.pop_back();
    }

  // No promotable pointer arguments.
  if (PointerArgs.empty()) return false;

  // Okay, promote all of the arguments are rewrite the callees!
  DoPromotion(F, PointerArgs);
  return true;
}

bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const {
  // We can only promote this argument if all of the uses are loads...
  std::vector<LoadInst*> Loads;
  for (Value::use_iterator UI = Arg->use_begin(), E = Arg->use_end();
       UI != E; ++UI)
    if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
      if (LI->isVolatile()) return false;  // Don't hack volatile loads
      Loads.push_back(LI);
    } else
      return false;

  if (Loads.empty()) return true;  // No users, dead argument.

  const Type *LoadTy = cast<PointerType>(Arg->getType())->getElementType();
  unsigned LoadSize = getAnalysis<TargetData>().getTypeSize(LoadTy);

  // Okay, now we know that the argument is only used by load instructions.
  // Check to see if the pointer is guaranteed to not be modified from entry of
  // the function to each of the load instructions.
  Function &F = *Arg->getParent();

  // Because there could be several/many load instructions, remember which
  // blocks we know to be transparent to the load.
  std::set<BasicBlock*> TranspBlocks;

  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();

  for (unsigned i = 0, e = Loads.size(); i != e; ++i) {
    // Check to see if the load is invalidated from the start of the block to
    // the load itself.
    LoadInst *Load = Loads[i];
    BasicBlock *BB = Load->getParent();
    if (AA.canInstructionRangeModify(BB->front(), *Load, Arg, LoadSize))
      return false;  // Pointer is invalidated!

    // Now check every path from the entry block to the load for transparency.
    // To do this, we perform a depth first search on the inverse CFG from the
    // loading block.
    for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
      for (idf_ext_iterator<BasicBlock*> I = idf_ext_begin(*PI, TranspBlocks),
             E = idf_ext_end(*PI, TranspBlocks); I != E; ++I)
        if (AA.canBasicBlockModify(**I, Arg, LoadSize))
          return false;
  }

  // If the path from the entry of the function to each load is free of
  // instructions that potentially invalidate the load, we can make the
  // transformation!
  return true;
}

void ArgPromotion::DoPromotion(Function *F, std::vector<Argument*> &Args2Prom) {
  std::set<Argument*> ArgsToPromote(Args2Prom.begin(), Args2Prom.end());

  // Start by computing a new prototype for the function, which is the same as
  // the old function, but has modified arguments.
  const FunctionType *FTy = F->getFunctionType();
  std::vector<const Type*> Params;

  for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I)
    if (!ArgsToPromote.count(I)) {
      Params.push_back(I->getType());
    } else if (!I->use_empty()) {
      Params.push_back(cast<PointerType>(I->getType())->getElementType());
      ++NumArgumentsPromoted;
    } else {
      ++NumArgumentsDead;
    }

  const Type *RetTy = FTy->getReturnType();

  // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
  // have zero fixed arguments.
  bool ExtraArgHack = false;
  if (Params.empty() && FTy->isVarArg()) {
    ExtraArgHack = true;
    Params.push_back(Type::IntTy);
  }
  FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg());

   // Create the new function body and insert it into the module...
  Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
  F->getParent()->getFunctionList().insert(F, NF);

  // Loop over all of the callers of the function, transforming the call sites
  // to pass in the loaded pointers.
  //
  std::vector<Value*> Args;
  while (!F->use_empty()) {
    CallSite CS = CallSite::get(F->use_back());
    Instruction *Call = CS.getInstruction();

    // Make sure the caller of this function is revisited.
    if (Call->getParent()->getParent()->hasInternalLinkage())
      WorkList.insert(Call->getParent()->getParent());

    // Loop over the operands, deleting dead ones...
    CallSite::arg_iterator AI = CS.arg_begin();
    for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I, ++AI)
      if (!ArgsToPromote.count(I))
        Args.push_back(*AI);          // Unmodified argument
      else if (!I->use_empty()) {
        // Non-dead instruction
        Args.push_back(new LoadInst(*AI, (*AI)->getName()+".val", Call));
      }

    if (ExtraArgHack)
      Args.push_back(Constant::getNullValue(Type::IntTy));

    // Push any varargs arguments on the list
    for (; AI != CS.arg_end(); ++AI)
      Args.push_back(*AI);

    Instruction *New;
    if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
      New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
                           Args, "", Call);
    } else {
      New = new CallInst(NF, Args, "", Call);
    }
    Args.clear();

    if (!Call->use_empty()) {
      Call->replaceAllUsesWith(New);
      std::string Name = Call->getName();
      Call->setName("");
      New->setName(Name);
    }

    // Finally, remove the old call from the program, reducing the use-count of
    // F.
    Call->getParent()->getInstList().erase(Call);
  }

  // Since we have now created the new function, splice the body of the old
  // function right into the new function, leaving the old rotting hulk of the
  // function empty.
  NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList());

  // Loop over the argument list, transfering uses of the old arguments over to
  // the new arguments, also transfering over the names as well.
  //
  for (Function::aiterator I = F->abegin(), E = F->aend(), I2 = NF->abegin();
       I != E; ++I)
    if (!ArgsToPromote.count(I)) {
      // If this is an unmodified argument, move the name and users over to the
      // new version.
      I->replaceAllUsesWith(I2);
      I2->setName(I->getName());
      ++I2;
    } else if (!I->use_empty()) {
      // Otherwise, if we promoted this argument, then all users are load
      // instructions, and all loads should be using the new argument that we
      // added.
      DEBUG(std::cerr << "*** Promoted argument '" << I->getName()
                      << "' of function '" << F->getName() << "'\n");
      I2->setName(I->getName()+".val");
      while (!I->use_empty()) {
        LoadInst *LI = cast<LoadInst>(I->use_back());
        LI->replaceAllUsesWith(I2);
        LI->getParent()->getInstList().erase(LI);
      }
      ++I2;
    }

  // Now that the old function is dead, delete it.
  F->getParent()->getFunctionList().erase(F);
}
<commit_msg>Fix another minor bug, exposed by perlbmk<commit_after>//===-- ArgumentPromotion.cpp - Promote 'by reference' arguments ----------===//
//
//                     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 pass promotes "by reference" arguments to be "by value" arguments.  In
// practice, this means looking for internal functions that have pointer
// arguments.  If we can prove, through the use of alias analysis, that that an
// argument is *only* loaded, then we can pass the value into the function
// instead of the address of the value.  This can cause recursive simplification
// of code, and lead to the elimination of allocas, especially in C++ template
// code like the STL.
//
// Note that this transformation could also be done for arguments that are only
// stored to (returning the value instead), but we do not currently handle that
// case.
//
// Note that we should be able to promote pointers to structures that are only
// loaded from as well.  The danger is creating way to many arguments, so this
// transformation should be limited to 3 element structs or something.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
#include "Support/Debug.h"
#include "Support/DepthFirstIterator.h"
#include "Support/Statistic.h"
#include <set>
using namespace llvm;

namespace {
  Statistic<> NumArgumentsPromoted("argpromotion",
                                   "Number of pointer arguments promoted");
  Statistic<> NumArgumentsDead("argpromotion",
                               "Number of dead pointer args eliminated");

  /// ArgPromotion - The 'by reference' to 'by value' argument promotion pass.
  ///
  class ArgPromotion : public Pass {
    // WorkList - The set of internal functions that we have yet to process.  As
    // we eliminate arguments from a function, we push all callers into this set
    // so that the by reference argument can be bubbled out as far as possible.
    // This set contains only internal functions.
    std::set<Function*> WorkList;
  public:
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<AliasAnalysis>();
      AU.addRequired<TargetData>();
    }

    virtual bool run(Module &M);
  private:
    bool PromoteArguments(Function *F);
    bool isSafeToPromoteArgument(Argument *Arg) const;
    void DoPromotion(Function *F, std::vector<Argument*> &ArgsToPromote);
  };

  RegisterOpt<ArgPromotion> X("argpromotion",
                              "Promote 'by reference' arguments to scalars");
}

Pass *llvm::createArgumentPromotionPass() {
  return new ArgPromotion();
}

bool ArgPromotion::run(Module &M) {
  bool Changed = false;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (I->hasInternalLinkage()) {
      WorkList.insert(I);

      // If there are any constant pointer refs pointing to this function,
      // eliminate them now if possible.
      ConstantPointerRef *CPR = 0;
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI)
        if ((CPR = dyn_cast<ConstantPointerRef>(*UI)))
          break;  // Found one!
      if (CPR) {
        // See if we can transform all users to use the function directly.
        while (!CPR->use_empty()) {
          User *TheUser = CPR->use_back();
          if (!isa<Constant>(TheUser) && !isa<GlobalVariable>(TheUser)) {
            Changed = true;
            TheUser->replaceUsesOfWith(CPR, I);
          } else {
            // We won't be able to eliminate all users.  :(
            WorkList.erase(I);  // Minor efficiency win.
            break;
          }
        }

        // If we nuked all users of the CPR, kill the CPR now!
        if (CPR->use_empty()) {
          CPR->destroyConstant();
          Changed = true;
        }
      }
    }

  while (!WorkList.empty()) {
    Function *F = *WorkList.begin();
    WorkList.erase(WorkList.begin());

    if (PromoteArguments(F))    // Attempt to promote an argument.
      Changed = true;           // Remember that we changed something.
  }

  return Changed;
}

bool ArgPromotion::PromoteArguments(Function *F) {
  assert(F->hasInternalLinkage() && "We can only process internal functions!");

  // First check: see if there are any pointer arguments!  If not, quick exit.
  std::vector<Argument*> PointerArgs;
  for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I)
    if (isa<PointerType>(I->getType()))
      PointerArgs.push_back(I);
  if (PointerArgs.empty()) return false;

  // Second check: make sure that all callers are direct callers.  We can't
  // transform functions that have indirect callers.
  for (Value::use_iterator UI = F->use_begin(), E = F->use_end();
       UI != E; ++UI) {
    CallSite CS = CallSite::get(*UI);
    if (Instruction *I = CS.getInstruction()) {
      // Ensure that this call site is CALLING the function, not passing it as
      // an argument.
      for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
           AI != E; ++AI)
        if (*AI == F) return false;   // Passing the function address in!
    } else {
      return false;  // Cannot promote an indirect call!
    }
  }

  // Check to see which arguments are promotable.  If an argument is not
  // promotable, remove it from the PointerArgs vector.
  for (unsigned i = 0; i != PointerArgs.size(); ++i)
    if (!isSafeToPromoteArgument(PointerArgs[i])) {
      std::swap(PointerArgs[i--], PointerArgs.back());
      PointerArgs.pop_back();
    }

  // No promotable pointer arguments.
  if (PointerArgs.empty()) return false;

  // Okay, promote all of the arguments are rewrite the callees!
  DoPromotion(F, PointerArgs);
  return true;
}

bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const {
  // We can only promote this argument if all of the uses are loads...
  std::vector<LoadInst*> Loads;
  for (Value::use_iterator UI = Arg->use_begin(), E = Arg->use_end();
       UI != E; ++UI)
    if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
      if (LI->isVolatile()) return false;  // Don't hack volatile loads
      Loads.push_back(LI);
    } else
      return false;

  if (Loads.empty()) return true;  // No users, dead argument.

  const Type *LoadTy = cast<PointerType>(Arg->getType())->getElementType();
  unsigned LoadSize = getAnalysis<TargetData>().getTypeSize(LoadTy);

  // Okay, now we know that the argument is only used by load instructions.
  // Check to see if the pointer is guaranteed to not be modified from entry of
  // the function to each of the load instructions.
  Function &F = *Arg->getParent();

  // Because there could be several/many load instructions, remember which
  // blocks we know to be transparent to the load.
  std::set<BasicBlock*> TranspBlocks;

  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();

  for (unsigned i = 0, e = Loads.size(); i != e; ++i) {
    // Check to see if the load is invalidated from the start of the block to
    // the load itself.
    LoadInst *Load = Loads[i];
    BasicBlock *BB = Load->getParent();
    if (AA.canInstructionRangeModify(BB->front(), *Load, Arg, LoadSize))
      return false;  // Pointer is invalidated!

    // Now check every path from the entry block to the load for transparency.
    // To do this, we perform a depth first search on the inverse CFG from the
    // loading block.
    for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
      for (idf_ext_iterator<BasicBlock*> I = idf_ext_begin(*PI, TranspBlocks),
             E = idf_ext_end(*PI, TranspBlocks); I != E; ++I)
        if (AA.canBasicBlockModify(**I, Arg, LoadSize))
          return false;
  }

  // If the path from the entry of the function to each load is free of
  // instructions that potentially invalidate the load, we can make the
  // transformation!
  return true;
}

void ArgPromotion::DoPromotion(Function *F, std::vector<Argument*> &Args2Prom) {
  std::set<Argument*> ArgsToPromote(Args2Prom.begin(), Args2Prom.end());

  // Start by computing a new prototype for the function, which is the same as
  // the old function, but has modified arguments.
  const FunctionType *FTy = F->getFunctionType();
  std::vector<const Type*> Params;

  for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I)
    if (!ArgsToPromote.count(I)) {
      Params.push_back(I->getType());
    } else if (!I->use_empty()) {
      Params.push_back(cast<PointerType>(I->getType())->getElementType());
      ++NumArgumentsPromoted;
    } else {
      ++NumArgumentsDead;
    }

  const Type *RetTy = FTy->getReturnType();

  // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
  // have zero fixed arguments.
  bool ExtraArgHack = false;
  if (Params.empty() && FTy->isVarArg()) {
    ExtraArgHack = true;
    Params.push_back(Type::IntTy);
  }
  FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg());

   // Create the new function body and insert it into the module...
  Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
  F->getParent()->getFunctionList().insert(F, NF);

  // Loop over all of the callers of the function, transforming the call sites
  // to pass in the loaded pointers.
  //
  std::vector<Value*> Args;
  while (!F->use_empty()) {
    CallSite CS = CallSite::get(F->use_back());
    Instruction *Call = CS.getInstruction();

    // Make sure the caller of this function is revisited.
    if (Call->getParent()->getParent()->hasInternalLinkage())
      WorkList.insert(Call->getParent()->getParent());

    // Loop over the operands, deleting dead ones...
    CallSite::arg_iterator AI = CS.arg_begin();
    for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I, ++AI)
      if (!ArgsToPromote.count(I))
        Args.push_back(*AI);          // Unmodified argument
      else if (!I->use_empty()) {
        // Non-dead instruction
        Args.push_back(new LoadInst(*AI, (*AI)->getName()+".val", Call));
      }

    if (ExtraArgHack)
      Args.push_back(Constant::getNullValue(Type::IntTy));

    // Push any varargs arguments on the list
    for (; AI != CS.arg_end(); ++AI)
      Args.push_back(*AI);

    Instruction *New;
    if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
      New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
                           Args, "", Call);
    } else {
      New = new CallInst(NF, Args, "", Call);
    }
    Args.clear();

    if (!Call->use_empty()) {
      Call->replaceAllUsesWith(New);
      std::string Name = Call->getName();
      Call->setName("");
      New->setName(Name);
    }

    // Finally, remove the old call from the program, reducing the use-count of
    // F.
    Call->getParent()->getInstList().erase(Call);
  }

  // Since we have now created the new function, splice the body of the old
  // function right into the new function, leaving the old rotting hulk of the
  // function empty.
  NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList());

  // Loop over the argument list, transfering uses of the old arguments over to
  // the new arguments, also transfering over the names as well.
  //
  for (Function::aiterator I = F->abegin(), E = F->aend(), I2 = NF->abegin();
       I != E; ++I)
    if (!ArgsToPromote.count(I)) {
      // If this is an unmodified argument, move the name and users over to the
      // new version.
      I->replaceAllUsesWith(I2);
      I2->setName(I->getName());
      ++I2;
    } else if (!I->use_empty()) {
      // Otherwise, if we promoted this argument, then all users are load
      // instructions, and all loads should be using the new argument that we
      // added.
      DEBUG(std::cerr << "*** Promoted argument '" << I->getName()
                      << "' of function '" << F->getName() << "'\n");
      I2->setName(I->getName()+".val");
      while (!I->use_empty()) {
        LoadInst *LI = cast<LoadInst>(I->use_back());
        LI->replaceAllUsesWith(I2);
        LI->getParent()->getInstList().erase(LI);
      }
      ++I2;
    }

  // Now that the old function is dead, delete it.
  F->getParent()->getFunctionList().erase(F);
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/browser_context.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/browser_main.h"
#include "libcef/browser/browser_message_filter.h"
#include "libcef/browser/browser_settings.h"
#include "libcef/browser/context.h"
#include "libcef/browser/resource_dispatcher_host_delegate.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/cef_switches.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "content/public/browser/access_token_store.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/common/content_switches.h"
#include "googleurl/src/gurl.h"

namespace {

// In-memory store for access tokens used by geolocation.
class CefAccessTokenStore : public content::AccessTokenStore {
 public:
  CefAccessTokenStore() {}

  virtual void LoadAccessTokens(
      const LoadAccessTokensCallbackType& callback) OVERRIDE {
    callback.Run(access_token_set_,
        _Context->browser_context()->GetRequestContext());
  }

  virtual void SaveAccessToken(
      const GURL& server_url, const string16& access_token) OVERRIDE {
    access_token_set_[server_url] = access_token;
  }

 private:
  AccessTokenSet access_token_set_;
};

}  // namespace

class CefMediaObserver : public content::MediaObserver {
 public:
  CefMediaObserver() {}
  virtual ~CefMediaObserver() {}

  virtual void OnDeleteAudioStream(void* host, int stream_id) OVERRIDE {}

  virtual void OnSetAudioStreamPlaying(void* host, int stream_id,
                                       bool playing) OVERRIDE {}
  virtual void OnSetAudioStreamStatus(void* host, int stream_id,
                                      const std::string& status) OVERRIDE {}
  virtual void OnSetAudioStreamVolume(void* host, int stream_id,
                                      double volume) OVERRIDE {}
  virtual void OnMediaEvent(int render_process_id,
                            const media::MediaLogEvent& event) OVERRIDE {}
  virtual void OnCaptureDevicesOpened(
      int render_process_id,
      int render_view_id,
      const content::MediaStreamDevices& devices) OVERRIDE {}
  virtual void OnCaptureDevicesClosed(
      int render_process_id,
      int render_view_id,
      const content::MediaStreamDevices& devices) OVERRIDE {}
};

CefContentBrowserClient::CefContentBrowserClient()
    : browser_main_parts_(NULL) {
}

CefContentBrowserClient::~CefContentBrowserClient() {
}

content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts(
    const content::MainFunctionParams& parameters) {
  browser_main_parts_ = new CefBrowserMainParts(parameters);
  return browser_main_parts_;
}

void CefContentBrowserClient::RenderProcessHostCreated(
    content::RenderProcessHost* host) {
  host->GetChannel()->AddFilter(new CefBrowserMessageFilter(host));
}

void CefContentBrowserClient::AppendExtraCommandLineSwitches(
    CommandLine* command_line, int child_process_id) {
  std::string process_type =
      command_line->GetSwitchValueASCII(switches::kProcessType);
  if (process_type == switches::kRendererProcess) {
      // Propagate the following switches to the renderer command line (along
      // with any associated values) if present in the browser command line.
      static const char* const kSwitchNames[] = {
        switches::kLogFile,
        switches::kLogSeverity,
        switches::kProductVersion,
        switches::kLocale,
        switches::kResourcesDirPath,
        switches::kLocalesDirPath,
        switches::kPackLoadingDisabled,
      };
      const CommandLine& browser_cmd = *CommandLine::ForCurrentProcess();
      command_line->CopySwitchesFrom(browser_cmd, kSwitchNames,
                                     arraysize(kSwitchNames));
  }
}

content::MediaObserver* CefContentBrowserClient::GetMediaObserver() {
  // TODO(cef): Return NULL once it's supported. See crbug.com/116113.
  if (!media_observer_.get())
     media_observer_.reset(new CefMediaObserver());
  return media_observer_.get();
}

content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() {
  return new CefAccessTokenStore;
}

void CefContentBrowserClient::ResourceDispatcherHostCreated() {
  resource_dispatcher_host_delegate_.reset(
      new CefResourceDispatcherHostDelegate());
  content::ResourceDispatcherHost::Get()->SetDelegate(
      resource_dispatcher_host_delegate_.get());
}

void CefContentBrowserClient::OverrideWebkitPrefs(
    content::RenderViewHost* rvh,
    const GURL& url,
    webkit_glue::WebPreferences* prefs) {
  CefRefPtr<CefBrowserHostImpl> browser =
      CefBrowserHostImpl::GetBrowserForHost(rvh);
  DCHECK(browser.get());

  // Populate WebPreferences based on CefBrowserSettings.
  BrowserToWebSettings(browser->settings(), *prefs);
}

std::string CefContentBrowserClient::GetDefaultDownloadName() {
  return "download";
}
<commit_msg>Propagate logging command-line parameters to all processes (issue #717).<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/browser_context.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/browser_main.h"
#include "libcef/browser/browser_message_filter.h"
#include "libcef/browser/browser_settings.h"
#include "libcef/browser/context.h"
#include "libcef/browser/resource_dispatcher_host_delegate.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/cef_switches.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "content/public/browser/access_token_store.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/common/content_switches.h"
#include "googleurl/src/gurl.h"

namespace {

// In-memory store for access tokens used by geolocation.
class CefAccessTokenStore : public content::AccessTokenStore {
 public:
  CefAccessTokenStore() {}

  virtual void LoadAccessTokens(
      const LoadAccessTokensCallbackType& callback) OVERRIDE {
    callback.Run(access_token_set_,
        _Context->browser_context()->GetRequestContext());
  }

  virtual void SaveAccessToken(
      const GURL& server_url, const string16& access_token) OVERRIDE {
    access_token_set_[server_url] = access_token;
  }

 private:
  AccessTokenSet access_token_set_;
};

}  // namespace

class CefMediaObserver : public content::MediaObserver {
 public:
  CefMediaObserver() {}
  virtual ~CefMediaObserver() {}

  virtual void OnDeleteAudioStream(void* host, int stream_id) OVERRIDE {}

  virtual void OnSetAudioStreamPlaying(void* host, int stream_id,
                                       bool playing) OVERRIDE {}
  virtual void OnSetAudioStreamStatus(void* host, int stream_id,
                                      const std::string& status) OVERRIDE {}
  virtual void OnSetAudioStreamVolume(void* host, int stream_id,
                                      double volume) OVERRIDE {}
  virtual void OnMediaEvent(int render_process_id,
                            const media::MediaLogEvent& event) OVERRIDE {}
  virtual void OnCaptureDevicesOpened(
      int render_process_id,
      int render_view_id,
      const content::MediaStreamDevices& devices) OVERRIDE {}
  virtual void OnCaptureDevicesClosed(
      int render_process_id,
      int render_view_id,
      const content::MediaStreamDevices& devices) OVERRIDE {}
};

CefContentBrowserClient::CefContentBrowserClient()
    : browser_main_parts_(NULL) {
}

CefContentBrowserClient::~CefContentBrowserClient() {
}

content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts(
    const content::MainFunctionParams& parameters) {
  browser_main_parts_ = new CefBrowserMainParts(parameters);
  return browser_main_parts_;
}

void CefContentBrowserClient::RenderProcessHostCreated(
    content::RenderProcessHost* host) {
  host->GetChannel()->AddFilter(new CefBrowserMessageFilter(host));
}

void CefContentBrowserClient::AppendExtraCommandLineSwitches(
    CommandLine* command_line, int child_process_id) {
  const CommandLine& browser_cmd = *CommandLine::ForCurrentProcess();

  {
    // Propagate the following switches to all command lines (along with any
    // associated values) if present in the browser command line.
    static const char* const kSwitchNames[] = {
      switches::kLogFile,
      switches::kLogSeverity,
    };
    command_line->CopySwitchesFrom(browser_cmd, kSwitchNames,
                                   arraysize(kSwitchNames));
  }

  std::string process_type =
      command_line->GetSwitchValueASCII(switches::kProcessType);
  if (process_type == switches::kRendererProcess) {
    // Propagate the following switches to the renderer command line (along with
    // any associated values) if present in the browser command line.
    static const char* const kSwitchNames[] = {
      switches::kProductVersion,
      switches::kLocale,
      switches::kResourcesDirPath,
      switches::kLocalesDirPath,
      switches::kPackLoadingDisabled,
    };
    command_line->CopySwitchesFrom(browser_cmd, kSwitchNames,
                                   arraysize(kSwitchNames));
  }
}

content::MediaObserver* CefContentBrowserClient::GetMediaObserver() {
  // TODO(cef): Return NULL once it's supported. See crbug.com/116113.
  if (!media_observer_.get())
     media_observer_.reset(new CefMediaObserver());
  return media_observer_.get();
}

content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() {
  return new CefAccessTokenStore;
}

void CefContentBrowserClient::ResourceDispatcherHostCreated() {
  resource_dispatcher_host_delegate_.reset(
      new CefResourceDispatcherHostDelegate());
  content::ResourceDispatcherHost::Get()->SetDelegate(
      resource_dispatcher_host_delegate_.get());
}

void CefContentBrowserClient::OverrideWebkitPrefs(
    content::RenderViewHost* rvh,
    const GURL& url,
    webkit_glue::WebPreferences* prefs) {
  CefRefPtr<CefBrowserHostImpl> browser =
      CefBrowserHostImpl::GetBrowserForHost(rvh);
  DCHECK(browser.get());

  // Populate WebPreferences based on CefBrowserSettings.
  BrowserToWebSettings(browser->settings(), *prefs);
}

std::string CefContentBrowserClient::GetDefaultDownloadName() {
  return "download";
}
<|endoftext|>