<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p10/procedures/hwp/perv/p10_setup_sbe_config.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2020                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p10_setup_sbe_config.C
///
/// @brief proc setup sbe config
//------------------------------------------------------------------------------
// *HWP HW Maintainer   : Anusha Reddy (anusrang@in.ibm.com)
// *HWP FW Maintainer   : Raja Das (rajadas2@in.ibm.com)
// *HWP Consumed by     : FSP
//------------------------------------------------------------------------------

#include <p10_setup_sbe_config.H>
#include <p10_sbe_scratch_regs.H>
#include <p10_scom_perv.H>

// description in header
fapi2::ReturnCode p10_setup_sbe_config(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip)
{
    using namespace scomt::perv;

    FAPI_INF("p10_setup_sbe_config::  Entering ...");

    fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;

    // when running in Hostboot context, use SCOM to reach master only
    bool l_use_scom = false;

    if (fapi2::is_platform<fapi2::PLAT_HOSTBOOT>())
    {
        fapi2::ATTR_PROC_SBE_MASTER_CHIP_Type l_sbe_master_chip;

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_SBE_MASTER_CHIP, i_target_chip, l_sbe_master_chip),
                 "Error from FAPI_ATTR_GET (ATTR_PROC_SBE_MASTER_CHIP");

        l_use_scom = (l_sbe_master_chip == fapi2::ENUM_ATTR_PROC_SBE_MASTER_CHIP_TRUE);
    }
    // clear secure access bit if instructed to disable security
    else
    {
        fapi2::ATTR_SECURITY_MODE_Type l_attr_security_mode;
        fapi2::buffer<uint32_t> l_cbs_cs_reg;

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SECURITY_MODE, FAPI_SYSTEM, l_attr_security_mode),
                 "Error from FAPI_ATTR_GET (ATTR_SECURITY_MODE)");

        if (!l_attr_security_mode)
        {
            // The Secure Access Bit is only writeable on DD1 chips,
            // so we won't need to put an EC level switch in here.
            FAPI_DBG("Attempting to disable security");
            FAPI_TRY(fapi2::getCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_CBS_CS_FSI,
                                            l_cbs_cs_reg),
                     "Error reading CBS Control/Status register");

            l_cbs_cs_reg.clearBit<FSXCOMP_FSXLOG_CBS_CS_SECURE_ACCESS_BIT>();

            FAPI_TRY(fapi2::putCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_CBS_CS_FSI,
                                            l_cbs_cs_reg),
                     "Error writing CBS Control/Status register");
        }

    }

    // set fused mode behavior
    {
        fapi2::ATTR_FUSED_CORE_MODE_Type l_attr_fused_core_mode;
        fapi2::ATTR_CORE_LPAR_MODE_POLICY_Type l_attr_core_lpar_mode_policy;
        fapi2::ATTR_CORE_LPAR_MODE_Type l_attr_core_lpar_mode;
        fapi2::buffer<uint64_t> l_perv_ctrl0;

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CORE_LPAR_MODE_POLICY, FAPI_SYSTEM, l_attr_core_lpar_mode_policy),
                 "Error from FAPI_ATTR_GET (ATTR_CORE_LPAR_MODE_POLICY)");

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FUSED_CORE_MODE, FAPI_SYSTEM, l_attr_fused_core_mode),
                 "Error from FAPI_ATTR_GET (ATTR_FUSED_CORE_MODE)");

        if (l_attr_core_lpar_mode_policy == fapi2::ENUM_ATTR_CORE_LPAR_MODE_POLICY_FOLLOW_FUSED_STATE)
        {
            if (l_attr_fused_core_mode == fapi2::ENUM_ATTR_FUSED_CORE_MODE_CORE_FUSED)
            {
                l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_CORE;
            }
            else
            {
                l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_THREAD;
            }
        }
        else if (l_attr_core_lpar_mode_policy == fapi2::ENUM_ATTR_CORE_LPAR_MODE_POLICY_LPAR_PER_CORE)
        {
            l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_CORE;
        }
        else
        {
            l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_THREAD;
        }

        if (l_use_scom)
        {
            FAPI_TRY(fapi2::getScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_RW,
                                    l_perv_ctrl0),
                     "Error reading PERV_CTRL0 (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            FAPI_TRY(fapi2::getCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error reading PERV_CTRL0 (cfam)");
            l_perv_ctrl0.insert<0, 32, 0>(l_perv_ctrl0_cfam);
        }

        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_OTP_SCOM_FUSED_CORE_MODE>(
            l_attr_fused_core_mode == fapi2::ENUM_ATTR_FUSED_CORE_MODE_CORE_FUSED);
        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_EX_SINGLE_LPAR_EN_DC>(
            l_attr_core_lpar_mode);

        if (l_use_scom)
        {
            FAPI_TRY(fapi2::putScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_RW,
                                    l_perv_ctrl0),
                     "Error writing PERV_CTRL0 (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            l_perv_ctrl0_cfam.insert<0, 32, 0>(l_perv_ctrl0);
            FAPI_TRY(fapi2::putCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error writing PERV_CTRL0 (cfam)");
        }

        // copy
        if (l_use_scom)
        {
            FAPI_TRY(fapi2::getScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_COPY_RW,
                                    l_perv_ctrl0),
                     "Error reading PERV_CTRL0_COPY (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            FAPI_TRY(fapi2::getCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_COPY_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error reading PERV_CTRL0_COPY (cfam)");
            l_perv_ctrl0.insert<0, 32, 0>(l_perv_ctrl0_cfam);
        }

        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_OTP_SCOM_FUSED_CORE_MODE>(
            l_attr_fused_core_mode == fapi2::ENUM_ATTR_FUSED_CORE_MODE_CORE_FUSED);
        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_EX_SINGLE_LPAR_EN_DC>(
            l_attr_core_lpar_mode);

        if (l_use_scom)
        {
            FAPI_TRY(fapi2::putScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_COPY_RW,
                                    l_perv_ctrl0),
                     "Error writing PERV_CTRL0_COPY (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            l_perv_ctrl0_cfam.insert<0, 32, 0>(l_perv_ctrl0);
            FAPI_TRY(fapi2::putCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_COPY_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error writing PERV_CTRL0_COPY (cfam)");
        }
    }

    // configure mailbox scratch registers
    {
        FAPI_TRY(p10_sbe_scratch_regs_update(i_target_chip, true, l_use_scom),
                 "Error from p10_sbe_scratch_regs_update");
    }

fapi_try_exit:
    FAPI_INF("p10_setup_sbe_config: Exiting ...");
    return fapi2::current_err;

}
<commit_msg>disable security on non-primary chips from Hostboot<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p10/procedures/hwp/perv/p10_setup_sbe_config.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2020                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p10_setup_sbe_config.C
///
/// @brief proc setup sbe config
//------------------------------------------------------------------------------
// *HWP HW Maintainer   : Anusha Reddy (anusrang@in.ibm.com)
// *HWP FW Maintainer   : Raja Das (rajadas2@in.ibm.com)
// *HWP Consumed by     : FSP
//------------------------------------------------------------------------------

#include <p10_setup_sbe_config.H>
#include <p10_sbe_scratch_regs.H>
#include <p10_scom_perv.H>

// description in header
fapi2::ReturnCode p10_setup_sbe_config(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip)
{
    using namespace scomt::perv;

    FAPI_INF("p10_setup_sbe_config::  Entering ...");

    fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;

    // when running in Hostboot context, use SCOM to reach master only
    bool l_use_scom = false;

    if (fapi2::is_platform<fapi2::PLAT_HOSTBOOT>())
    {
        fapi2::ATTR_PROC_SBE_MASTER_CHIP_Type l_sbe_master_chip;

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_SBE_MASTER_CHIP, i_target_chip, l_sbe_master_chip),
                 "Error from FAPI_ATTR_GET (ATTR_PROC_SBE_MASTER_CHIP");

        l_use_scom = (l_sbe_master_chip == fapi2::ENUM_ATTR_PROC_SBE_MASTER_CHIP_TRUE);
    }

    // clear secure access bit if instructed to disable security
    {
        fapi2::ATTR_SECURITY_MODE_Type l_attr_security_mode;

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SECURITY_MODE, FAPI_SYSTEM, l_attr_security_mode),
                 "Error from FAPI_ATTR_GET (ATTR_SECURITY_MODE)");

        if (!l_attr_security_mode)
        {
            // The Secure Access Bit is only writeable on DD1 chips,
            // so we won't need to put an EC level switch in here.
            FAPI_DBG("Attempting to disable security");

            if (l_use_scom)
            {
                fapi2::buffer<uint64_t> l_cbs_cs;

                FAPI_TRY(fapi2::getScom(i_target_chip,
                                        FSXCOMP_FSXLOG_CBS_CS,
                                        l_cbs_cs),
                         "Error reading CBS Control/Status register (scom)");

                l_cbs_cs.clearBit<FSXCOMP_FSXLOG_CBS_CS_SECURE_ACCESS_BIT>();

                FAPI_TRY(fapi2::putScom(i_target_chip,
                                        FSXCOMP_FSXLOG_CBS_CS,
                                        l_cbs_cs),
                         "Error writing CBS Control/Status register (scom)");
            }
            else
            {
                fapi2::buffer<uint32_t> l_cbs_cs;

                FAPI_TRY(fapi2::getCfamRegister(i_target_chip,
                                                FSXCOMP_FSXLOG_CBS_CS_FSI,
                                                l_cbs_cs),
                         "Error reading CBS Control/Status register (cfam)");

                l_cbs_cs.clearBit<FSXCOMP_FSXLOG_CBS_CS_SECURE_ACCESS_BIT>();

                FAPI_TRY(fapi2::putCfamRegister(i_target_chip,
                                                FSXCOMP_FSXLOG_CBS_CS_FSI,
                                                l_cbs_cs),
                         "Error writing CBS Control/Status register (cfam)");
            }
        }
    }

    // set fused mode behavior
    {
        fapi2::ATTR_FUSED_CORE_MODE_Type l_attr_fused_core_mode;
        fapi2::ATTR_CORE_LPAR_MODE_POLICY_Type l_attr_core_lpar_mode_policy;
        fapi2::ATTR_CORE_LPAR_MODE_Type l_attr_core_lpar_mode;
        fapi2::buffer<uint64_t> l_perv_ctrl0;

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CORE_LPAR_MODE_POLICY, FAPI_SYSTEM, l_attr_core_lpar_mode_policy),
                 "Error from FAPI_ATTR_GET (ATTR_CORE_LPAR_MODE_POLICY)");

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FUSED_CORE_MODE, FAPI_SYSTEM, l_attr_fused_core_mode),
                 "Error from FAPI_ATTR_GET (ATTR_FUSED_CORE_MODE)");

        if (l_attr_core_lpar_mode_policy == fapi2::ENUM_ATTR_CORE_LPAR_MODE_POLICY_FOLLOW_FUSED_STATE)
        {
            if (l_attr_fused_core_mode == fapi2::ENUM_ATTR_FUSED_CORE_MODE_CORE_FUSED)
            {
                l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_CORE;
            }
            else
            {
                l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_THREAD;
            }
        }
        else if (l_attr_core_lpar_mode_policy == fapi2::ENUM_ATTR_CORE_LPAR_MODE_POLICY_LPAR_PER_CORE)
        {
            l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_CORE;
        }
        else
        {
            l_attr_core_lpar_mode = fapi2::ENUM_ATTR_CORE_LPAR_MODE_LPAR_PER_THREAD;
        }

        if (l_use_scom)
        {
            FAPI_TRY(fapi2::getScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_RW,
                                    l_perv_ctrl0),
                     "Error reading PERV_CTRL0 (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            FAPI_TRY(fapi2::getCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error reading PERV_CTRL0 (cfam)");
            l_perv_ctrl0.insert<0, 32, 0>(l_perv_ctrl0_cfam);
        }

        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_OTP_SCOM_FUSED_CORE_MODE>(
            l_attr_fused_core_mode == fapi2::ENUM_ATTR_FUSED_CORE_MODE_CORE_FUSED);
        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_EX_SINGLE_LPAR_EN_DC>(
            l_attr_core_lpar_mode);

        if (l_use_scom)
        {
            FAPI_TRY(fapi2::putScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_RW,
                                    l_perv_ctrl0),
                     "Error writing PERV_CTRL0 (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            l_perv_ctrl0_cfam.insert<0, 32, 0>(l_perv_ctrl0);
            FAPI_TRY(fapi2::putCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error writing PERV_CTRL0 (cfam)");
        }

        // copy
        if (l_use_scom)
        {
            FAPI_TRY(fapi2::getScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_COPY_RW,
                                    l_perv_ctrl0),
                     "Error reading PERV_CTRL0_COPY (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            FAPI_TRY(fapi2::getCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_COPY_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error reading PERV_CTRL0_COPY (cfam)");
            l_perv_ctrl0.insert<0, 32, 0>(l_perv_ctrl0_cfam);
        }

        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_OTP_SCOM_FUSED_CORE_MODE>(
            l_attr_fused_core_mode == fapi2::ENUM_ATTR_FUSED_CORE_MODE_CORE_FUSED);
        l_perv_ctrl0.writeBit<FSXCOMP_FSXLOG_PERV_CTRL0_TP_EX_SINGLE_LPAR_EN_DC>(
            l_attr_core_lpar_mode);

        if (l_use_scom)
        {
            FAPI_TRY(fapi2::putScom(i_target_chip,
                                    FSXCOMP_FSXLOG_PERV_CTRL0_COPY_RW,
                                    l_perv_ctrl0),
                     "Error writing PERV_CTRL0_COPY (scom)");
        }
        else
        {
            fapi2::buffer<uint32_t> l_perv_ctrl0_cfam;
            l_perv_ctrl0_cfam.insert<0, 32, 0>(l_perv_ctrl0);
            FAPI_TRY(fapi2::putCfamRegister(i_target_chip,
                                            FSXCOMP_FSXLOG_PERV_CTRL0_COPY_FSI,
                                            l_perv_ctrl0_cfam),
                     "Error writing PERV_CTRL0_COPY (cfam)");
        }
    }

    // configure mailbox scratch registers
    {
        FAPI_TRY(p10_sbe_scratch_regs_update(i_target_chip, true, l_use_scom),
                 "Error from p10_sbe_scratch_regs_update");
    }

fapi_try_exit:
    FAPI_INF("p10_setup_sbe_config: Exiting ...");
    return fapi2::current_err;

}
<|endoftext|>


<commit_before>#include "..\header\int\Level.h"
#include "..\header\int\Component.h"
#include "..\header\int\Texture.h"

float Level::FindHeight(const Vector3& position){
	Vector3 localPos = transform.GlobalToLocal(position);

	Vector2 gridPos = Vector2(localPos.x, localPos.z);

	float currHeight = localPos.y;
	int currDepth = INT_MIN;
	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		if(iter->depth > currDepth && BoundsContains(gridPos, iter->ulCorner, iter->brCorner)){
			currDepth = iter->depth;
			currHeight = iter->floorHeight;
		}
	}

	localPos.y = currHeight;
	return transform.LocalToGlobal(localPos).y;
}

//Is pt contained in the AABB formed by ul (upper left) and br (bottom right)
bool BoundsContains(const Vector2& pt, const Vector2& ul, const Vector2& br){
	return pt.x > ul.x && pt.y > ul.y
		&& pt.x < br.x && pt.y < br.y;
}

Vector3 Level::ResolveCollisions(const Vector3& from, const Vector3& to){
	Vector3 localFrom = transform.GlobalToLocal(from);
	Vector3 localTo   = transform.GlobalToLocal(to);

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Vector3 edge1 = Vector3(iter->start.x, iter->height, iter->start.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 edge2 = Vector3(iter->end.x, 0, iter->end.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 normal = CrossProduct(edge1, edge2);

		//cout << "LocalFrom: " << localFrom.x << ", " << localFrom.y << ", " << localFrom.z << endl;
		//Vector3(iter->start.x, 0, iter->start.y).Print();

		float fromDist = DotProduct(localFrom - Vector3(iter->start.x, 0, iter->start.y), normal);
		float   toDist = DotProduct(localTo   - Vector3(iter->start.x, 0, iter->start.y), normal);
		//cout << "ToDist: " << toDist << "  FromDist: " << fromDist << endl;
		if(toDist * fromDist < 0){
			return from;
		}
	}

	return to;
}

void Level::SetRenderingCompMesh(RenderingComp& rend, const string& texture){
	rend.entity = -1;

	vector<Vector3> verts;
	vector<Vector2> uvs;

	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		Floor floor = *iter;
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.brCorner.y));

		uvs.push_back(Vector2(0,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Wall wall = *iter;

		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.start.x, wall.height, wall.start.y));
		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));

		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));
		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.end.x,   0,           wall.end.y));

		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	rend.vertCount = verts.size();

	glGenBuffers(1, &rend.verticesVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.verticesVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3)*verts.size(), &(verts[0]), GL_STATIC_DRAW);

	glGenBuffers(1, &rend.uvsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.uvsVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2)*uvs.size(), &(uvs[0]), GL_STATIC_DRAW);

	rend.texObject = new Texture(GL_TEXTURE_2D, texture);
	rend.texObject->Load();
	rend.texture = rend.texObject->textureObj;

	string shader = "data/shader";
	string vertShader;
	string fragShader;
	if(! (ReadFile(shader + ".vs", vertShader) && ReadFile(shader + ".fs", fragShader))){
		cout << "Error reading files: " << shader << ".vs and " << shader << ".fs" << endl;
		return;
	}

	rend.shaderProgram = glCreateProgram();
	AddShader(rend.shaderProgram, vertShader.c_str(), GL_VERTEX_SHADER);
	AddShader(rend.shaderProgram, fragShader.c_str(), GL_FRAGMENT_SHADER);

	glLinkProgram(rend.shaderProgram);

	GLint Success;
	glGetProgramiv(rend.shaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		char ErrorLog[1024];
		glGetProgramInfoLog(rend.shaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
	}

	glValidateProgram(rend.shaderProgram);
}

<commit_msg>Walls only block movement along their length, not infinitely in each direction.<commit_after>#include "..\header\int\Level.h"
#include "..\header\int\Component.h"
#include "..\header\int\Texture.h"

float Level::FindHeight(const Vector3& position){
	Vector3 localPos = transform.GlobalToLocal(position);

	Vector2 gridPos = Vector2(localPos.x, localPos.z);

	float currHeight = localPos.y;
	int currDepth = INT_MIN;
	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		if(iter->depth > currDepth && BoundsContains(gridPos, iter->ulCorner, iter->brCorner)){
			currDepth = iter->depth;
			currHeight = iter->floorHeight;
		}
	}

	localPos.y = currHeight;
	return transform.LocalToGlobal(localPos).y;
}

//Is pt contained in the AABB formed by ul (upper left) and br (bottom right)
bool BoundsContains(const Vector2& pt, const Vector2& ul, const Vector2& br){
	return pt.x > ul.x && pt.y > ul.y
		&& pt.x < br.x && pt.y < br.y;
}

Vector3 Level::ResolveCollisions(const Vector3& from, const Vector3& to){
	Vector3 localFrom = transform.GlobalToLocal(from);
	Vector3 localTo   = transform.GlobalToLocal(to);

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Vector3 edge1 = Vector3(iter->start.x, iter->height, iter->start.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 edge2 = Vector3(iter->end.x, 0, iter->end.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 normal = CrossProduct(edge1, edge2);

		float fromDist = DotProduct(localFrom - Vector3(iter->start.x, 0, iter->start.y), normal);
		float   toDist = DotProduct(localTo   - Vector3(iter->start.x, 0, iter->start.y), normal);
		//cout << "ToDist: " << toDist << "  FromDist: " << fromDist << endl;
		if(toDist * fromDist < 0){
			Vector2 floorProjection = Vector2(localFrom.x, localFrom.z);
			Vector2 wallDiff = floorProjection - iter->start;
			Vector2 wallVec = (iter->end - iter->start).Normalized();
			float overlap = DotProduct(wallDiff, wallVec);

			if(overlap < (iter->end - iter->start).Magnitude() && overlap > 0){
				return from;
			}
		}
	}

	return to;
}

void Level::SetRenderingCompMesh(RenderingComp& rend, const string& texture){
	rend.entity = -1;

	vector<Vector3> verts;
	vector<Vector2> uvs;

	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		Floor floor = *iter;
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.brCorner.y));

		uvs.push_back(Vector2(0,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Wall wall = *iter;

		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.start.x, wall.height, wall.start.y));
		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));

		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));
		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.end.x,   0,           wall.end.y));

		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	rend.vertCount = verts.size();

	glGenBuffers(1, &rend.verticesVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.verticesVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3)*verts.size(), &(verts[0]), GL_STATIC_DRAW);

	glGenBuffers(1, &rend.uvsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.uvsVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2)*uvs.size(), &(uvs[0]), GL_STATIC_DRAW);

	rend.texObject = new Texture(GL_TEXTURE_2D, texture);
	rend.texObject->Load();
	rend.texture = rend.texObject->textureObj;

	string shader = "data/shader";
	string vertShader;
	string fragShader;
	if(! (ReadFile(shader + ".vs", vertShader) && ReadFile(shader + ".fs", fragShader))){
		cout << "Error reading files: " << shader << ".vs and " << shader << ".fs" << endl;
		return;
	}

	rend.shaderProgram = glCreateProgram();
	AddShader(rend.shaderProgram, vertShader.c_str(), GL_VERTEX_SHADER);
	AddShader(rend.shaderProgram, fragShader.c_str(), GL_FRAGMENT_SHADER);

	glLinkProgram(rend.shaderProgram);

	GLint Success;
	glGetProgramiv(rend.shaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		char ErrorLog[1024];
		glGetProgramInfoLog(rend.shaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
	}

	glValidateProgram(rend.shaderProgram);
}

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/accessors/p9_get_mvpd_ring.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// $Id: p9_get_mvpd_ring.H,v 1.1 2012/07/19 22:00:38 mjjones Exp $
/**
 *  @file p9_get_mvpd_ring.H
 *
 *  @brief Prototype for getMvpdRing() -
 *          get a repair ring from a MVPD record
 */

#ifndef    _HWP_GETMVPDRING_
#define    _HWP_GETMVPDRING_

#include   <fapi2.H>

namespace fapi2
{

// function pointer typedef definition for HWP call support
typedef ReturnCode (*getMvpdRing_FP_t) (
    MvpdRecord,
    MvpdKeyword,
    const Target<TARGET_TYPE_PROC_CHIP>&,
    const uint8_t,
    const uint64_t,
    const uint8_t,
    uint8_t*,
    uint32_t& );

extern "C"
{
    /**
     * @brief   get specified ring from MVPD for the specified target CPU.
     *
     * A Ring Id Chiplet Id should be unique in the mvpd Record.
     * The code does not validate. No assumption should be made on which would
     * be returned if there are multiple.
     *
     * @param i_record          -   Record enumerator
     * @param i_keyword         -   Keyword enumerator
     * Supported Rings are:
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDR
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDG
     * @param i_fapiTarget      -   cpu target
     * @param i_chipletId       -   Chiplet ID
     * @param i_evenOddMask     -   Mask to choose even or odd EX. O for all other chiplets
     * @param i_ringId          -   Ring ID
     * @param i_pRingBuf        -   pointer to a buffer allocated by the caller
     *                              to receive the ring header and data.
     *                              if NULL, the size of the min buffer required
     *                              buffer will be returned in io_rRingBufsize
     *                              with rc FAPI_RC_SUCCESS.
     * @param io_rRingBufsize   -   in:     size of ring buffer that caller has
     *                                      allocated
     *                              out:    number of BYTES that were copied to the
     *                                      output buffer.
     *                                      If the ring was not found, an error
     *                                      will be returned and this will be 0.
     *                                      If the output buffer is not big enough,
     *                                      an error will be returned and this will
     *                                      be the minimum size required.
     *                              The buffer contains the CompressedScanData
     *                              structure followed by compressed data. The
     *                              caller does compression and decompression.
     *  Buffer:   io_rRingBufsize returns xNN.
     *    byte x0  CompressedScanData structure (rs4 header)
     *    byte x18 compressed data (sizeof CompressedScanData is 0x18)
     *    byte xNN last byte of compressed data
     *
     * @return fapi2::ReturnCode -   FAPI_RC_SUCCESS if success,
     *                               relevant error code for failure.
     */
    ReturnCode getMvpdRing( MvpdRecord     i_record,
                            MvpdKeyword    i_keyword,
                            const Target<TARGET_TYPE_PROC_CHIP>&
                            i_fapiTarget,
                            const uint8_t  i_chipletId,
                            const uint64_t i_evenOddMask,
                            const uint8_t  i_ringId,
                            uint8_t*       io_pRingBuf,
                            uint32_t&      io_rRingBufsize );

}
}
#endif
<commit_msg>TOR space reductions<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/accessors/p9_get_mvpd_ring.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// $Id: p9_get_mvpd_ring.H,v 1.1 2012/07/19 22:00:38 mjjones Exp $
/**
 *  @file p9_get_mvpd_ring.H
 *
 *  @brief Prototype for getMvpdRing() -
 *          get a repair ring from a MVPD record
 */

#ifndef    _HWP_GETMVPDRING_
#define    _HWP_GETMVPDRING_

#include   <fapi2.H>

namespace fapi2
{

// function pointer typedef definition for HWP call support
typedef ReturnCode (*getMvpdRing_FP_t) (
    MvpdRecord,
    MvpdKeyword,
    const Target<TARGET_TYPE_PROC_CHIP>&,
    const uint8_t,
    const uint64_t,
    const uint8_t,
    uint8_t*,
    uint32_t& );

extern "C"
{
    /**
     * @brief   get specified ring from MVPD for the specified target CPU.
     *
     * A Ring Id Chiplet Id should be unique in the mvpd Record.
     * The code does not validate. No assumption should be made on which would
     * be returned if there are multiple.
     *
     * @param i_record          -   Record enumerator
     * @param i_keyword         -   Keyword enumerator
     * Supported Rings are:
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDR
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDG
     * @param i_fapiTarget      -   cpu target
     * @param i_chipletId       -   Chiplet ID
     * @param i_evenOdd         -   Even (0) or odd (1) EX. Disregarded for other chiplets.
     * @param i_ringId          -   Ring ID
     * @param i_pRingBuf        -   pointer to a buffer allocated by the caller
     *                              to receive the ring header and data.
     *                              if NULL, the size of the min buffer required
     *                              buffer will be returned in io_rRingBufsize
     *                              with rc FAPI_RC_SUCCESS.
     * @param io_rRingBufsize   -   in:     size of ring buffer that caller has
     *                                      allocated
     *                              out:    number of BYTES that were copied to the
     *                                      output buffer.
     *                                      If the ring was not found, an error
     *                                      will be returned and this will be 0.
     *                                      If the output buffer is not big enough,
     *                                      an error will be returned and this will
     *                                      be the minimum size required.
     *                              The buffer contains the CompressedScanData
     *                              structure followed by compressed data. The
     *                              caller does compression and decompression.
     *  Buffer:   io_rRingBufsize returns xNN.
     *    byte x0  CompressedScanData structure (rs4 header)
     *    byte x0C compressed data (sizeof CompressedScanData is 0x0C)
     *    byte xNN last byte of compressed data
     *
     * @return fapi2::ReturnCode -   FAPI_RC_SUCCESS if success,
     *                               relevant error code for failure.
     */
    ReturnCode getMvpdRing( MvpdRecord     i_record,
                            MvpdKeyword    i_keyword,
                            const Target<TARGET_TYPE_PROC_CHIP>&
                            i_fapiTarget,
                            const uint8_t  i_chipletId,
                            const uint8_t  i_evenOdd,
                            const uint8_t  i_ringId,
                            uint8_t*       io_pRingBuf,
                            uint32_t&      io_rRingBufsize );

}
}
#endif
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_FAST_HELPER_HXX
#define INCLUDED_FAST_HELPER_HXX

#include <iostream>
#include <resourcemodel/QNameToString.hxx>
#include "OOXMLFastContextHandler.hxx"
#include "ooxmlLoggers.hxx"
namespace writerfilter {

namespace ooxml
{
using namespace ::std;
using namespace ::com::sun::star;
using namespace ::com::sun::star::xml::sax;

template <class T>
class OOXMLFastHelper
{
public:
    static uno::Reference<XFastContextHandler> createAndSetParent
    (OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId);

    static uno::Reference<XFastContextHandler> createAndSetParentAndDefine
    (OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId, Id nDefine);

    static uno::Reference<XFastContextHandler> createAndSetParentRef
    (OOXMLFastContextHandler * pHandler, sal_uInt32 nToken,
     const uno::Reference < xml::sax::XFastAttributeList > & Attribs);

    static void newProperty(OOXMLFastContextHandler * pHandler,
                            Id nId,
                            const OUString & rValue);

    static void newProperty(OOXMLFastContextHandler * pHandler,
                            Id nId, sal_Int32 nValue);

    static void mark(OOXMLFastContextHandler * pHandler,
                     Id nId,
                     const OUString & rValue);

    static void attributes
    (OOXMLFastContextHandler * pContext,
     const uno::Reference < xml::sax::XFastAttributeList > & Attribs);
};

template <class T>
uno::Reference<XFastContextHandler>
OOXMLFastHelper<T>::createAndSetParent
(OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId)
{
#ifdef DEBUG_HELPER
    debug_logger->startElement("helper.createAndSetParent");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("id", (*QNameToString::Instance())(nId));
#endif

    OOXMLFastContextHandler * pTmp = new T(pHandler);

    pTmp->setToken(nToken);
    pTmp->setId(nId);

#ifdef DEBUG_CREATE
    debug_logger->startElement("createAndSetParent");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("token", fastTokenToId(pTmp->getToken()));
    debug_logger->attribute("id", (*QNameToString::Instance())(nId));

    debug_logger->startElement("created");
    debug_logger->addTag(pTmp->toTag());
    debug_logger->endElement("created");
    debug_logger->endElement("helper.createAndSetParent");
#endif

    uno::Reference<XFastContextHandler> aResult(pTmp);

    return aResult;
}

template <class T>
uno::Reference<XFastContextHandler>
OOXMLFastHelper<T>::createAndSetParentAndDefine
(OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId, Id nDefine)
{
#ifdef DEBUG_HELPER
    debug_logger->startElement("helper.createAndSetParentAndDefine");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("id", (*QNameToString::Instance())(nId));

    static char buffer[16];
    snprintf(buffer, sizeof(buffer), "0x%08" SAL_PRIxUINT32, nId);

    debug_logger->attribute("idnum", buffer);
#endif

    OOXMLFastContextHandler * pTmp = new T(pHandler);

    pTmp->setToken(nToken);
    pTmp->setId(nId);
    pTmp->setDefine(nDefine);

#ifdef DEBUG_HELPER
    debug_logger->startElement("created");
    debug_logger->addTag(pTmp->toTag());
    debug_logger->endElement("created");
    debug_logger->endElement("helper.createAndSetParentAndDefine");
#endif

    uno::Reference<XFastContextHandler> aResult(pTmp);

    return aResult;
}

template <class T>
uno::Reference<XFastContextHandler>
OOXMLFastHelper<T>::createAndSetParentRef
(OOXMLFastContextHandler * pHandler, sal_uInt32 nToken,
 const uno::Reference < xml::sax::XFastAttributeList > & Attribs)
{
#ifdef DEBUG_HELPER
    debug_logger->startElement("helper.createAndSetParentRef");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("type", fastTokenToId(nToken));
#endif

    boost::shared_ptr<OOXMLFastContextHandler> pTmp(new T(pHandler));

    uno::Reference<XFastContextHandler> xChild =
        pTmp->createFastChildContext(nToken, Attribs);

    OOXMLFastContextHandler * pResult = NULL;
    if (xChild.is())
    {
        pResult = dynamic_cast<OOXMLFastContextHandler *>(xChild.get());
        pResult->setToken(nToken);
        pResult->setParent(pHandler);
    }

#ifdef DEBUG_HELPER
    debug_logger->startElement("created");
    debug_logger->addTag(pTmp->toTag());
    debug_logger->endElement("created");
    debug_logger->endElement("helper.createAndSetParentRef");
#endif

    return xChild;
}

template <class T>
void OOXMLFastHelper<T>::newProperty(OOXMLFastContextHandler * pHandler,
                                     Id nId,
                                     const OUString & rValue)
{
    OOXMLValue::Pointer_t pVal(new T(rValue));

#ifdef DEBUG_HELPER
    string aStr = (*QNameToString::Instance())(nId);

    debug_logger->startElement("newProperty-from-string");
    debug_logger->attribute("name", aStr);
    debug_logger->attribute
        ("value",
         OUStringToOString
         (rValue, RTL_TEXTENCODING_ASCII_US).getStr());

    if (aStr.empty())
        debug_logger->element( "unknown-qname" );
#endif

    pHandler->newProperty(nId, pVal);

#ifdef DEBUG_HELPER
    debug_logger->endElement();
#endif

}

template <class T>
void OOXMLFastHelper<T>::newProperty(OOXMLFastContextHandler * pHandler,
                                     Id nId,
                                     sal_Int32 nVal)
{
    OOXMLValue::Pointer_t pVal(new T(nVal));

#ifdef DEBUG_HELPER
    string aStr = (*QNameToString::Instance())(nId);

    debug_logger->startElement("helper.newProperty-from-int");
    debug_logger->attribute("name", aStr);
    debug_logger->attribute("value", pVal->toString());

    if (aStr.empty())
        debug_logger->element("unknown-qname");

    debug_logger->endElement();
#endif

    pHandler->newProperty(nId, pVal);
}

template <class T>
void OOXMLFastHelper<T>::mark(OOXMLFastContextHandler * pHandler,
                              Id nId,
                              const OUString & rValue)
{
    OOXMLValue::Pointer_t pVal(new T(rValue));

#ifdef DEBUG_HELPER
    string aStr = (*QNameToString::Instance())(nId);

    debug_logger->startElement("helper.mark");
    debug_logger->attribute("name", aStr);
    debug_logger->attribute("value",
        OUStringToOString
        (rValue, RTL_TEXTENCODING_ASCII_US).getStr());

    if (aStr.empty())
        debug_logger->element("unknown-qname");

    debug_logger->endElement();
#endif

    pHandler->mark(nId, pVal);
}
}}
#endif // INCLUDED_FAST_HELPER_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Reduce scope<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_FAST_HELPER_HXX
#define INCLUDED_FAST_HELPER_HXX

#include <iostream>
#include <resourcemodel/QNameToString.hxx>
#include "OOXMLFastContextHandler.hxx"
#include "ooxmlLoggers.hxx"
namespace writerfilter {

namespace ooxml
{
using namespace ::std;
using namespace ::com::sun::star;
using namespace ::com::sun::star::xml::sax;

template <class T>
class OOXMLFastHelper
{
public:
    static uno::Reference<XFastContextHandler> createAndSetParent
    (OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId);

    static uno::Reference<XFastContextHandler> createAndSetParentAndDefine
    (OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId, Id nDefine);

    static uno::Reference<XFastContextHandler> createAndSetParentRef
    (OOXMLFastContextHandler * pHandler, sal_uInt32 nToken,
     const uno::Reference < xml::sax::XFastAttributeList > & Attribs);

    static void newProperty(OOXMLFastContextHandler * pHandler,
                            Id nId,
                            const OUString & rValue);

    static void newProperty(OOXMLFastContextHandler * pHandler,
                            Id nId, sal_Int32 nValue);

    static void mark(OOXMLFastContextHandler * pHandler,
                     Id nId,
                     const OUString & rValue);

    static void attributes
    (OOXMLFastContextHandler * pContext,
     const uno::Reference < xml::sax::XFastAttributeList > & Attribs);
};

template <class T>
uno::Reference<XFastContextHandler>
OOXMLFastHelper<T>::createAndSetParent
(OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId)
{
#ifdef DEBUG_HELPER
    debug_logger->startElement("helper.createAndSetParent");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("id", (*QNameToString::Instance())(nId));
#endif

    OOXMLFastContextHandler * pTmp = new T(pHandler);

    pTmp->setToken(nToken);
    pTmp->setId(nId);

#ifdef DEBUG_CREATE
    debug_logger->startElement("createAndSetParent");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("token", fastTokenToId(pTmp->getToken()));
    debug_logger->attribute("id", (*QNameToString::Instance())(nId));

    debug_logger->startElement("created");
    debug_logger->addTag(pTmp->toTag());
    debug_logger->endElement("created");
    debug_logger->endElement("helper.createAndSetParent");
#endif

    uno::Reference<XFastContextHandler> aResult(pTmp);

    return aResult;
}

template <class T>
uno::Reference<XFastContextHandler>
OOXMLFastHelper<T>::createAndSetParentAndDefine
(OOXMLFastContextHandler * pHandler, sal_uInt32 nToken, Id nId, Id nDefine)
{
#ifdef DEBUG_HELPER
    debug_logger->startElement("helper.createAndSetParentAndDefine");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("id", (*QNameToString::Instance())(nId));

    static char buffer[16];
    snprintf(buffer, sizeof(buffer), "0x%08" SAL_PRIxUINT32, nId);

    debug_logger->attribute("idnum", buffer);
#endif

    OOXMLFastContextHandler * pTmp = new T(pHandler);

    pTmp->setToken(nToken);
    pTmp->setId(nId);
    pTmp->setDefine(nDefine);

#ifdef DEBUG_HELPER
    debug_logger->startElement("created");
    debug_logger->addTag(pTmp->toTag());
    debug_logger->endElement("created");
    debug_logger->endElement("helper.createAndSetParentAndDefine");
#endif

    uno::Reference<XFastContextHandler> aResult(pTmp);

    return aResult;
}

template <class T>
uno::Reference<XFastContextHandler>
OOXMLFastHelper<T>::createAndSetParentRef
(OOXMLFastContextHandler * pHandler, sal_uInt32 nToken,
 const uno::Reference < xml::sax::XFastAttributeList > & Attribs)
{
#ifdef DEBUG_HELPER
    debug_logger->startElement("helper.createAndSetParentRef");
    debug_logger->attribute("context", pHandler->getType());
    debug_logger->attribute("type", fastTokenToId(nToken));
#endif

    boost::shared_ptr<OOXMLFastContextHandler> pTmp(new T(pHandler));

    uno::Reference<XFastContextHandler> xChild =
        pTmp->createFastChildContext(nToken, Attribs);

    if (xChild.is())
    {
        OOXMLFastContextHandler* pResult = dynamic_cast<OOXMLFastContextHandler *>(xChild.get());
        pResult->setToken(nToken);
        pResult->setParent(pHandler);
    }

#ifdef DEBUG_HELPER
    debug_logger->startElement("created");
    debug_logger->addTag(pTmp->toTag());
    debug_logger->endElement("created");
    debug_logger->endElement("helper.createAndSetParentRef");
#endif

    return xChild;
}

template <class T>
void OOXMLFastHelper<T>::newProperty(OOXMLFastContextHandler * pHandler,
                                     Id nId,
                                     const OUString & rValue)
{
    OOXMLValue::Pointer_t pVal(new T(rValue));

#ifdef DEBUG_HELPER
    string aStr = (*QNameToString::Instance())(nId);

    debug_logger->startElement("newProperty-from-string");
    debug_logger->attribute("name", aStr);
    debug_logger->attribute
        ("value",
         OUStringToOString
         (rValue, RTL_TEXTENCODING_ASCII_US).getStr());

    if (aStr.empty())
        debug_logger->element( "unknown-qname" );
#endif

    pHandler->newProperty(nId, pVal);

#ifdef DEBUG_HELPER
    debug_logger->endElement();
#endif

}

template <class T>
void OOXMLFastHelper<T>::newProperty(OOXMLFastContextHandler * pHandler,
                                     Id nId,
                                     sal_Int32 nVal)
{
    OOXMLValue::Pointer_t pVal(new T(nVal));

#ifdef DEBUG_HELPER
    string aStr = (*QNameToString::Instance())(nId);

    debug_logger->startElement("helper.newProperty-from-int");
    debug_logger->attribute("name", aStr);
    debug_logger->attribute("value", pVal->toString());

    if (aStr.empty())
        debug_logger->element("unknown-qname");

    debug_logger->endElement();
#endif

    pHandler->newProperty(nId, pVal);
}

template <class T>
void OOXMLFastHelper<T>::mark(OOXMLFastContextHandler * pHandler,
                              Id nId,
                              const OUString & rValue)
{
    OOXMLValue::Pointer_t pVal(new T(rValue));

#ifdef DEBUG_HELPER
    string aStr = (*QNameToString::Instance())(nId);

    debug_logger->startElement("helper.mark");
    debug_logger->attribute("name", aStr);
    debug_logger->attribute("value",
        OUStringToOString
        (rValue, RTL_TEXTENCODING_ASCII_US).getStr());

    if (aStr.empty())
        debug_logger->element("unknown-qname");

    debug_logger->endElement();
#endif

    pHandler->mark(nId, pVal);
}
}}
#endif // INCLUDED_FAST_HELPER_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


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

#include "cling/Interpreter/Value.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"
#include "cling/Utils/Casting.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/UTF8.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Sema.h"

#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_os_ostream.h"

namespace {

  ///\brief The allocation starts with this layout; it is followed by the
  ///  value's object at m_Payload. This class does not inherit from
  ///  llvm::RefCountedBase because deallocation cannot use this type but must
  ///  free the character array.

  class AllocatedValue {
  public:
    typedef void (*DtorFunc_t)(void*);

  private:
    ///\brief The destructor function.
    DtorFunc_t m_DtorFunc;

    ///\brief The size of the allocation (for arrays)
    size_t m_AllocSize;

    ///\brief The number of elements in the array
    size_t m_NElements;

    ///\brief The reference count - once 0, this object will be deallocated.
    /// Hopefully 2^55 - 1 references should be enough as the last byte is
    /// used for flag storage.
    enum { SizeBytes = sizeof(size_t), ConstructedByte = SizeBytes - 1 };
    union {
      size_t m_Count;
      char   m_Bytes[SizeBytes];
    };

    size_t UpdateRefCount(int Amount) {
      // Bit shift the bytes used in m_Bytes for representing an integer
      // respecting endian-ness and which of those bytes are significant.
      assert((Amount == 1 || Amount == -1) && "Invalid amount");
      union { size_t m_Count; char m_Bytes[SizeBytes]; } RC = { 0 };
      const size_t NBytes = SizeBytes - sizeof(char);
      const size_t Endian = llvm::sys::IsBigEndianHost;
      ::memcpy(&RC.m_Bytes[Endian], &m_Bytes[0], NBytes);
      RC.m_Count += Amount;
      ::memcpy(&m_Bytes[0], &RC.m_Bytes[Endian], NBytes);
      return RC.m_Count;
    }

    static AllocatedValue* FromPtr(void* Ptr) {
      return reinterpret_cast<AllocatedValue*>(reinterpret_cast<char*>(Ptr) -
                                               sizeof(AllocatedValue));
    }

    ///\brief Initialize the storage management part of the allocated object.
    ///  The allocator is referencing it, thus initialize m_RefCnt with 1.
    ///\param [in] dtorFunc - the function to be called before deallocation.
    AllocatedValue(size_t Size, size_t NElem, DtorFunc_t Dtor) :
      m_DtorFunc(Dtor), m_AllocSize(Size), m_NElements(NElem) {
      m_Count = 0;
      UpdateRefCount(1);
    }

  public:
    ///\brief Create an AllocatedValue whose lifetime is reference counted.
    /// \returns The address of the writeable client data.
    static void* Create(size_t Size, size_t NElem, DtorFunc_t Dtor) {
      char* Alloc = new char[sizeof(AllocatedValue) + Size];
      AllocatedValue* AV = new (Alloc) AllocatedValue(Size, NElem, Dtor);

      static_assert(std::is_standard_layout<AllocatedValue>::value, "padding");
      static_assert(sizeof(m_Count) == sizeof(m_Bytes), "union padding");
      static_assert(((offsetof(AllocatedValue, m_Count) + sizeof(m_Count)) %
                            SizeBytes) == 0,
                    "Buffer may not be machine aligned");
      assert(&Alloc[sizeof(AllocatedValue) - 1] == &AV->m_Bytes[SizeBytes - 1]
             && "Padded AllocatedValue");

      // Give back the first client writable byte.
      return AV->m_Bytes + SizeBytes;
    }

    static void Retain(void* Ptr) {
      FromPtr(Ptr)->UpdateRefCount(1);
    }

    ///\brief This object must be allocated as a char array. Deallocate it as
    ///   such.
    static void Release(void* Ptr) {
      AllocatedValue* AV = FromPtr(Ptr);
      if (AV->UpdateRefCount(-1) == 0) {
        if (AV->m_DtorFunc && AV->m_Bytes[ConstructedByte]) {
          assert(AV->m_NElements && "No elements!");
          char* Payload = reinterpret_cast<char*>(Ptr);
          const auto Skip = AV->m_AllocSize / AV->m_NElements;
          while (AV->m_NElements-- != 0)
            (*AV->m_DtorFunc)(Payload + AV->m_NElements * Skip);
        }
        this->~AllocatedValue();
        delete [] reinterpret_cast<char*>(AV);
      }
    }
  };
}

namespace cling {

  Value::Value(const Value& other):
    m_Storage(other.m_Storage), m_StorageType(other.m_StorageType),
    m_Type(other.m_Type), m_Interpreter(other.m_Interpreter) {
    if (other.needsManagedAllocation())
      AllocatedValue::Retain(m_Storage.m_Ptr);
  }

  Value::Value(clang::QualType clangTy, Interpreter& Interp, bool ArrayPtr) :
    m_StorageType(determineStorageType(clangTy, ArrayPtr)),
    m_Type(clangTy.getAsOpaquePtr()),
    m_Interpreter(&Interp) {
    if (needsManagedAllocation())
      ManagedAllocate();
  }

  Value& Value::operator =(const Value& other) {
    // Release old value.
    if (needsManagedAllocation())
      AllocatedValue::Release(m_Storage.m_Ptr);

    // Retain new one.
    m_Type = other.m_Type;
    m_Storage = other.m_Storage;
    m_StorageType = other.m_StorageType;
    m_Interpreter = other.m_Interpreter;
    if (needsManagedAllocation())
      AllocatedValue::Retain(m_Storage.m_Ptr);
    return *this;
  }

  Value& Value::operator =(Value&& other) {
    // Release old value.
    if (needsManagedAllocation())
      AllocatedValue::Release(m_Storage.m_Ptr);

    // Move new one.
    m_Type = other.m_Type;
    m_Storage = other.m_Storage;
    m_StorageType = other.m_StorageType;
    m_Interpreter = other.m_Interpreter;
    // Invalidate other so it will not release.
    other.m_StorageType = kUnsupportedType;

    return *this;
  }

  Value::~Value() {
    if (needsManagedAllocation())
      AllocatedValue::Release(m_Storage.m_Ptr);
  }

  clang::QualType Value::getType() const {
    return clang::QualType::getFromOpaquePtr(m_Type);
  }

  clang::ASTContext& Value::getASTContext() const {
    return m_Interpreter->getCI()->getASTContext();
  }

  bool Value::isValid() const { return !getType().isNull(); }

  bool Value::isVoid() const {
    const clang::ASTContext& Ctx = getASTContext();
    return isValid() && Ctx.hasSameType(getType(), Ctx.VoidTy);
  }

  size_t Value::GetNumberOfElements() const {
    if (const clang::ConstantArrayType* ArrTy
        = llvm::dyn_cast<clang::ConstantArrayType>(getType())) {
      llvm::APInt arrSize(sizeof(size_t)*8, 1);
      do {
        arrSize *= ArrTy->getSize();
        ArrTy = llvm::dyn_cast<clang::ConstantArrayType>(ArrTy->getElementType()
                                                         .getTypePtr());
      } while (ArrTy);
      return static_cast<size_t>(arrSize.getZExtValue());
    }
    return 1;
  }

  Value::EStorageType Value::determineStorageType(clang::QualType QT, bool AP) {
    const clang::Type* desugCanon = QT.getCanonicalType().getTypePtr();
    if (desugCanon->isSignedIntegerOrEnumerationType())
      return kSignedIntegerOrEnumerationType;
    else if (desugCanon->isUnsignedIntegerOrEnumerationType())
      return kUnsignedIntegerOrEnumerationType;
    else if (desugCanon->isRealFloatingType()) {
      const clang::BuiltinType* BT = desugCanon->getAs<clang::BuiltinType>();
      if (BT->getKind() == clang::BuiltinType::Double)
        return kDoubleType;
      else if (BT->getKind() == clang::BuiltinType::Float)
        return kFloatType;
      else if (BT->getKind() == clang::BuiltinType::LongDouble)
        return kLongDoubleType;
    } else if (desugCanon->isPointerType() || desugCanon->isObjectType()
               || desugCanon->isReferenceType()) {
      if (desugCanon->isRecordType() || desugCanon->isMemberPointerType()
          || (!AP && desugCanon->isConstantArrayType()))
        return kManagedAllocation;
      return kPointerType;
    }
    return kUnsupportedType;
  }

  void Value::ManagedAllocate() {
    assert(needsManagedAllocation() && "Does not need managed allocation");
    const clang::QualType Ty = getType();
    clang::QualType DtorTy = Ty;

    // For arrays we destruct the elements.
    if (const clang::ConstantArrayType* ArrTy =
            llvm::dyn_cast<clang::ConstantArrayType>(Ty.getTypePtr())) {
      DtorTy = ArrTy->getElementType();
    }

    AllocatedValue::DtorFunc_t DtorFunc = nullptr;
    if (const clang::RecordType* RTy = DtorTy->getAs<clang::RecordType>()) {
      DtorFunc = cling::utils::VoidToFunctionPtr<AllocatedValue::DtorFunc_t>(
          m_Interpreter->compileDtorCallFor(RTy->getDecl()));
    }

    m_Storage.m_Ptr = AllocatedValue::Create(
        getASTContext().getTypeSizeInChars(Ty).getQuantity(),
        GetNumberOfElements(), DtorFunc);
  }

  void Value::AssertOnUnsupportedTypeCast() const {
    assert("unsupported type in Value, cannot cast simplistically!" && 0);
  }

  namespace valuePrinterInternal {
    std::string printTypeInternal(const Value& V);
    std::string printValueInternal(const Value& V);
    extern const char* const kUndefined;
  } // end namespace valuePrinterInternal

  void Value::print(llvm::raw_ostream& Out, bool Escape) const {
    if (!m_Interpreter) {
      Out << valuePrinterInternal::kUndefined << "\n";
      return;
    }

    // Save the default type string representation so output can occur as one
    // operation (calling printValueInternal below may write to stderr).
    const std::string Type = valuePrinterInternal::printTypeInternal(*this);

    // Get the value string representation, by printValue() method overloading
    const std::string Val = cling::valuePrinterInternal::printValueInternal(*this);
    if (Escape) {
      const char* Data = Val.data();
      const size_t N = Val.size();
      switch (N ? Data[0] : 0) {
        case 'u': case 'U': case 'L':
          if (N < 3 || Data[1] != '\"')
            break;

          // Unicode string, encoded as Utf-8
        case '\"':
          if (N > 2 && Data[N-1] == '\"') {
            // Drop the terminating " so Utf-8 errors can be detected ("\xeA")
            Out << Type << ' ';
            utils::utf8::EscapeSequence().encode(Data, N-1, Out) << "\"\n";
            return;
          }
        default:
          break;
      }
    }
    Out << Type << ' ' << Val << '\n';
  }

  void Value::dump(bool Escape) const {
    print(cling::outs(), Escape);
  }
} // end namespace cling
<commit_msg>Make AllocatedValue allocate memory more dynamically based on the needs of the type.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/Value.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"
#include "cling/Utils/Casting.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/UTF8.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Sema.h"

#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_os_ostream.h"

namespace {

  ///\brief The layout/usage of memory allocated by AllocatedValue::Create
  /// is dependent on the the type of object it is representing.  If the type
  /// has a non-trival destructor then the memory base will point to either
  /// a full Destructable struct (when it is also an array whose size > 1), or
  /// a single DtorFunc_t value when the object is a single instance or an array
  /// with only 1 element.
  ///
  /// If neither of these are true (a POD or array to one), or directly follwing
  /// the prior two cases, is the memory location that can be used to placement
  /// new an AllocatedValue instance.
  ///
  /// The AllocatedValue instance ontains a single union for reference counting
  /// and flags of how the layout exists in memory.
  ///
  /// On 32-bit the reference count will max out a bit before 16.8 million.
  /// 64 bit limit is still extremely high (2^56)-1
  ///
  ///
  /// General layout of memory allocated by AllocatedValue::Create
  ///
  /// +---- Destructable ---+  <- Optional, allocated for arrays
  /// |                     |      TestFlag(kHasElements)
  /// |  Size               |
  /// |  Elements           |
  /// |  Dtor               |  <- Can exist without prior Destructable members
  /// |                     |      TestFlag(kHasDestructor)
  /// |                     |
  /// +---AllocatedValue ---+  <- This object
  /// |                     |      TestFlag(kHasElements)
  /// | union {             |
  /// |  size_t m_Count     |
  /// |  char   m_Bytes[8]  |  <- m_Bytes[7] is reserved for AllocatedValue
  /// | };                  |     & ValueExtractionSynthesizer writing info.
  /// |                     |
  /// +~~ Client Payload ~~~+  <- Returned from AllocatedValue::Create
  /// |                     |
  /// |                     |
  /// +---------------------+
  ///
  /// It may be possible to ignore the caching of this info all together and
  /// just figure out what to do in AllocatedValue::Release by passing the
  /// QualType and Interpreter, but am a bit weary of this for two reasons:
  ///
  ///  1. FIXME: There is still a bad lifetime cycle where a Value referencing
  ///     an Interpreter that has been destroyed is possible.
  ///  2. How that might interact with decl unloading, and the possibility of
  ///     a destructor no longer being defined after a cling::Value has been
  ///     created to represent a fuller state of the type.

  class AllocatedValue {
  public:
    typedef void (*DtorFunc_t)(void*);

  private:

    struct Destructable {
      ///\brief Size to skip to get the next element in the array.
      size_t Size;

      ///\brief Total number of elements in the array.
      size_t Elements;

      ///\brief The destructor function.
      DtorFunc_t Dtor;
    };

    ///\brief The reference count - once 0, this object will be deallocated.
    /// Hopefully 2^55 - 1 references should be enough as the last byte is
    /// used for flag storage.
    enum {
      SizeBytes = sizeof(size_t),
      FlagsByte = SizeBytes - 1,

      kConstructorRan = 1, // Used by ValueExtractionSynthesizer
      kHasDestructor = 2,
      kHasElements = 4
    };
    union {
      size_t m_Count;
      char   m_Bytes[SizeBytes];
    };

    bool TestFlags(unsigned F) const { return (m_Bytes[FlagsByte] & F) == F; }

    size_t UpdateRefCount(int Amount) {
      // Bit shift the bytes used in m_Bytes for representing an integer
      // respecting endian-ness and which of those bytes are significant.
      assert((Amount == 1 || Amount == -1) && "Invalid amount");
      union { size_t m_Count; char m_Bytes[SizeBytes]; } RC = { 0 };
      const size_t NBytes = SizeBytes - sizeof(char);
      const size_t Endian = llvm::sys::IsBigEndianHost;
      ::memcpy(&RC.m_Bytes[Endian], &m_Bytes[0], NBytes);
      RC.m_Count += Amount;
      ::memcpy(&m_Bytes[0], &RC.m_Bytes[Endian], NBytes);
      return RC.m_Count;
    }

    template <class T = AllocatedValue> static T* FromPtr(void* Ptr) {
      return reinterpret_cast<T*>(reinterpret_cast<char*>(Ptr) - sizeof(T));
    }

    ///\brief Initialize the reference count and flag management.
    /// Everything else is in a Destructable object before -this-
    AllocatedValue(char Info) {
      m_Count = 0;
      m_Bytes[FlagsByte] = Info;
      UpdateRefCount(1);
    }

  public:

    ///\brief Create an AllocatedValue.
    /// \returns The address of the writeable client data.
    static void* Create(size_t Size, size_t NElem, DtorFunc_t Dtor) {
      size_t AllocSize = sizeof(AllocatedValue) + Size;
      size_t ExtraSize = 0;
      char Flags = 0;
      if (Dtor) {
        // Only need the elements data for arrays larger than 1.
        if (NElem > 1) {
          Flags |= kHasElements;
          ExtraSize = sizeof(Destructable);
        } else
          ExtraSize = sizeof(DtorFunc_t);

        Flags |= kHasDestructor;
        AllocSize += ExtraSize;
      }

      char* Alloc = new char[AllocSize];

      if (Dtor) {
        // Move the Buffer ptr to where AllocatedValue begins
        Alloc += ExtraSize;
        // Now back up to get the location of the Destructable members
        // This is so writing to Destructable::Dtor will work when only
        // additional space for DtorFunc_t was written.
        Destructable* DS = FromPtr<Destructable>(Alloc);
        if (NElem > 1) {
          DS->Elements = NElem;
          // Hopefully there won't be any issues with object alignemnt of arrays
          // If there are, that would have to be dealt with here and write the
          // proper skip amount in DS->Size.
          DS->Size = Size / NElem;
        }
        DS->Dtor = Dtor;
      }

      AllocatedValue* AV = new (Alloc) AllocatedValue(Flags);

      // Just make sure alignment is as expected.
      static_assert(std::is_standard_layout<Destructable>::value, "padding");
      static_assert((sizeof(Destructable) % SizeBytes) == 0, "alignment");
      static_assert(std::is_standard_layout<AllocatedValue>::value, "padding");
      static_assert(sizeof(m_Count) == sizeof(m_Bytes), "union padding");
      static_assert(((offsetof(AllocatedValue, m_Count) + sizeof(m_Count)) %
                            SizeBytes) == 0,
                    "Buffer may not be machine aligned");
      // Validate the byte ValueExtractionSynthesizer will write too
      assert(&Alloc[sizeof(AllocatedValue) - 1] == &AV->m_Bytes[SizeBytes - 1]
             && "Padded AllocatedValue");

      // Give back the first client writable byte.
      return AV->m_Bytes + SizeBytes;
    }

    static void Retain(void* Ptr) {
      FromPtr(Ptr)->UpdateRefCount(1);
    }

    ///\brief This object must be allocated as a char array. Deallocate it as
    ///   such.
    static void Release(void* Ptr) {
      AllocatedValue* AV = FromPtr(Ptr);
      if (AV->UpdateRefCount(-1) == 0) {
        if (AV->TestFlags(kConstructorRan|kHasDestructor)) {
          Destructable* Dtor = FromPtr<Destructable>(AV);
          size_t Elements = 1, Size = 0;
          if (AV->TestFlags(kHasElements)) {
            Elements = Dtor->Elements;
            Size = Dtor->Size;
          }
          char* Payload = reinterpret_cast<char*>(Ptr);
          while (Elements-- != 0)
            (*Dtor->Dtor)(Payload + Elements * Size);
        }

        // Subtract the amount that was over-allocated from the base of -this-
        char* Allocated = reinterpret_cast<char*>(AV);
        if (AV->TestFlags(kHasElements))
          Allocated -= sizeof(Destructable);
        else if (AV->TestFlags(kHasDestructor))
          Allocated -= sizeof(DtorFunc_t);

        AV->~AllocatedValue();
        delete [] Allocated;
      }
    }
  };
}

namespace cling {

  Value::Value(const Value& other):
    m_Storage(other.m_Storage), m_StorageType(other.m_StorageType),
    m_Type(other.m_Type), m_Interpreter(other.m_Interpreter) {
    if (other.needsManagedAllocation())
      AllocatedValue::Retain(m_Storage.m_Ptr);
  }

  Value::Value(clang::QualType clangTy, Interpreter& Interp, bool ArrayPtr) :
    m_StorageType(determineStorageType(clangTy, ArrayPtr)),
    m_Type(clangTy.getAsOpaquePtr()),
    m_Interpreter(&Interp) {
    if (needsManagedAllocation())
      ManagedAllocate();
  }

  Value& Value::operator =(const Value& other) {
    // Release old value.
    if (needsManagedAllocation())
      AllocatedValue::Release(m_Storage.m_Ptr);

    // Retain new one.
    m_Type = other.m_Type;
    m_Storage = other.m_Storage;
    m_StorageType = other.m_StorageType;
    m_Interpreter = other.m_Interpreter;
    if (needsManagedAllocation())
      AllocatedValue::Retain(m_Storage.m_Ptr);
    return *this;
  }

  Value& Value::operator =(Value&& other) {
    // Release old value.
    if (needsManagedAllocation())
      AllocatedValue::Release(m_Storage.m_Ptr);

    // Move new one.
    m_Type = other.m_Type;
    m_Storage = other.m_Storage;
    m_StorageType = other.m_StorageType;
    m_Interpreter = other.m_Interpreter;
    // Invalidate other so it will not release.
    other.m_StorageType = kUnsupportedType;

    return *this;
  }

  Value::~Value() {
    if (needsManagedAllocation())
      AllocatedValue::Release(m_Storage.m_Ptr);
  }

  clang::QualType Value::getType() const {
    return clang::QualType::getFromOpaquePtr(m_Type);
  }

  clang::ASTContext& Value::getASTContext() const {
    return m_Interpreter->getCI()->getASTContext();
  }

  bool Value::isValid() const { return !getType().isNull(); }

  bool Value::isVoid() const {
    const clang::ASTContext& Ctx = getASTContext();
    return isValid() && Ctx.hasSameType(getType(), Ctx.VoidTy);
  }

  size_t Value::GetNumberOfElements() const {
    if (const clang::ConstantArrayType* ArrTy
        = llvm::dyn_cast<clang::ConstantArrayType>(getType())) {
      llvm::APInt arrSize(sizeof(size_t)*8, 1);
      do {
        arrSize *= ArrTy->getSize();
        ArrTy = llvm::dyn_cast<clang::ConstantArrayType>(ArrTy->getElementType()
                                                         .getTypePtr());
      } while (ArrTy);
      return static_cast<size_t>(arrSize.getZExtValue());
    }
    return 1;
  }

  Value::EStorageType Value::determineStorageType(clang::QualType QT, bool AP) {
    const clang::Type* desugCanon = QT.getCanonicalType().getTypePtr();
    if (desugCanon->isSignedIntegerOrEnumerationType())
      return kSignedIntegerOrEnumerationType;
    else if (desugCanon->isUnsignedIntegerOrEnumerationType())
      return kUnsignedIntegerOrEnumerationType;
    else if (desugCanon->isRealFloatingType()) {
      const clang::BuiltinType* BT = desugCanon->getAs<clang::BuiltinType>();
      if (BT->getKind() == clang::BuiltinType::Double)
        return kDoubleType;
      else if (BT->getKind() == clang::BuiltinType::Float)
        return kFloatType;
      else if (BT->getKind() == clang::BuiltinType::LongDouble)
        return kLongDoubleType;
    } else if (desugCanon->isPointerType() || desugCanon->isObjectType()
               || desugCanon->isReferenceType()) {
      if (desugCanon->isRecordType() || desugCanon->isMemberPointerType()
          || (!AP && desugCanon->isConstantArrayType()))
        return kManagedAllocation;
      return kPointerType;
    }
    return kUnsupportedType;
  }

  void Value::ManagedAllocate() {
    assert(needsManagedAllocation() && "Does not need managed allocation");
    const clang::QualType Ty = getType();
    clang::QualType DtorTy = Ty;

    // For arrays we destruct the elements.
    if (const clang::ConstantArrayType* ArrTy =
            llvm::dyn_cast<clang::ConstantArrayType>(Ty.getTypePtr())) {
      DtorTy = ArrTy->getElementType();
    }

    AllocatedValue::DtorFunc_t DtorFunc = nullptr;
    if (const clang::RecordType* RTy = DtorTy->getAs<clang::RecordType>()) {
      DtorFunc = cling::utils::VoidToFunctionPtr<AllocatedValue::DtorFunc_t>(
          m_Interpreter->compileDtorCallFor(RTy->getDecl()));
    }

    m_Storage.m_Ptr = AllocatedValue::Create(
        getASTContext().getTypeSizeInChars(Ty).getQuantity(),
        GetNumberOfElements(), DtorFunc);
  }

  void Value::AssertOnUnsupportedTypeCast() const {
    assert("unsupported type in Value, cannot cast simplistically!" && 0);
  }

  namespace valuePrinterInternal {
    std::string printTypeInternal(const Value& V);
    std::string printValueInternal(const Value& V);
    extern const char* const kUndefined;
  } // end namespace valuePrinterInternal

  void Value::print(llvm::raw_ostream& Out, bool Escape) const {
    if (!m_Interpreter) {
      Out << valuePrinterInternal::kUndefined << "\n";
      return;
    }

    // Save the default type string representation so output can occur as one
    // operation (calling printValueInternal below may write to stderr).
    const std::string Type = valuePrinterInternal::printTypeInternal(*this);

    // Get the value string representation, by printValue() method overloading
    const std::string Val = cling::valuePrinterInternal::printValueInternal(*this);
    if (Escape) {
      const char* Data = Val.data();
      const size_t N = Val.size();
      switch (N ? Data[0] : 0) {
        case 'u': case 'U': case 'L':
          if (N < 3 || Data[1] != '\"')
            break;

          // Unicode string, encoded as Utf-8
        case '\"':
          if (N > 2 && Data[N-1] == '\"') {
            // Drop the terminating " so Utf-8 errors can be detected ("\xeA")
            Out << Type << ' ';
            utils::utf8::EscapeSequence().encode(Data, N-1, Out) << "\"\n";
            return;
          }
        default:
          break;
      }
    }
    Out << Type << ' ' << Val << '\n';
  }

  void Value::dump(bool Escape) const {
    print(cling::outs(), Escape);
  }
} // end namespace cling
<|endoftext|>