<commit_before>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  llpcPatch.cpp
 * @brief LLPC source file: contains implementation of class Llpc::Patch.
 ***********************************************************************************************************************
 */
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/IR/IRPrintingPasses.h"
#include <llvm/IR/LegacyPassManager.h>
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h>
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include <llvm/Transforms/IPO/ForceFunctionAttrs.h>
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Scalar.h"
#include <llvm/Transforms/Scalar/GVN.h>
#include "llvm/Transforms/Scalar/InstSimplifyPass.h"
#include "llvm/Transforms/Scalar/Scalarizer.h"
#include "llvm/Transforms/Utils.h"
#include "llpcBuilder.h"
#include "llpcContext.h"
#include "llpcInternal.h"
#include "llpcPassManager.h"
#include "llpcPatch.h"
#include "llpcPatchCheckShaderCache.h"
#include "SPIRVInternal.h"

#define DEBUG_TYPE "llpc-patch"

using namespace llvm;

namespace llvm
{

namespace cl
{

// -disable-patch-opt: disable optimization for LLVM patching
opt<bool> DisablePatchOpt("disable-patch-opt", desc("Disable optimization for LLVM patching"));

// -include-llvm-ir: include LLVM IR as a separate section in the ELF binary
opt<bool> IncludeLlvmIr("include-llvm-ir",
                        desc("Include LLVM IR as a separate section in the ELF binary"),
                        init(false));

// -use-llvm-opt: Use LLVM's standard optimization set instead of the curated optimization set
opt<bool> UseLlvmOpt("use-llvm-opt",
                     desc("Use LLVM's standard optimization set instead of the curated optimization set"),
                     init(false));

} // cl

} // llvm

namespace Llpc
{

// =====================================================================================================================
// Add whole-pipeline patch passes to pass manager
void Patch::AddPasses(
    Context*              pContext,      // [in] LLPC context
    legacy::PassManager&  passMgr,       // [in/out] Pass manager to add passes to
    llvm::Timer*          pPatchTimer,   // [in] Timer to time patch passes with, nullptr if not timing
    llvm::Timer*          pOptTimer,     // [in] Timer to time LLVM optimization passes with, nullptr if not timing
    std::function<uint32_t(const Module*, uint32_t, ArrayRef<ArrayRef<uint8_t>>)>
                          checkShaderCacheFunc)
                                         // Callback function to check shader cache
{
    // Start timer for patching passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pPatchTimer, true));
    }

    // If using BuilderRecorder rather than BuilderImpl, replay the Builder calls now
    auto pBuilderReplayer = pContext->GetBuilder()->CreateBuilderReplayer();
    if (pBuilderReplayer != nullptr)
    {
        passMgr.add(pBuilderReplayer);
    }

    if (EnableOuts())
    {
        passMgr.add(createPrintModulePass(outs(),
                    "===============================================================================\n"
                    "// LLPC pipeline before-patching results\n"));
    }

    // Build null fragment shader if necessary
    passMgr.add(CreatePatchNullFragShader());

    // Patch resource collecting, remove inactive resources (should be the first preliminary pass)
    passMgr.add(CreatePatchResourceCollect());

    // Generate copy shader if necessary.
    passMgr.add(CreatePatchCopyShader());

    // Patch entry-point mutation (should be done before external library link)
    passMgr.add(CreatePatchEntryPointMutate());

    // Patch push constant loading (should be done before external library link)
    passMgr.add(CreatePatchPushConstOp());

    // Function inlining and remove dead functions after it
    passMgr.add(createAlwaysInlinerLegacyPass());
    passMgr.add(CreatePassDeadFuncRemove());

    // Patch input import and output export operations
    passMgr.add(CreatePatchInOutImportExport());

    // Patch descriptor load operations
    passMgr.add(CreatePatchDescriptorLoad());

    // Prior to general optimization, do function inlining and dead function removal once again
    passMgr.add(createAlwaysInlinerLegacyPass());
    passMgr.add(CreatePassDeadFuncRemove());

    // Check shader cache
    auto pCheckShaderCachePass = CreatePatchCheckShaderCache();
    passMgr.add(pCheckShaderCachePass);
    pCheckShaderCachePass->SetCallbackFunction(checkShaderCacheFunc);

    // Stop timer for patching passes and start timer for optimization passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pPatchTimer, false));
        passMgr.add(CreateStartStopTimer(pOptTimer, true));
    }

    // Prepare pipeline ABI but only set the calling conventions to AMDGPU ones for now.
    passMgr.add(CreatePatchPreparePipelineAbi(/* onlySetCallingConvs = */true));

    // Add some optimization passes

    // Need to run a first promote mem 2 reg to remove alloca's whose only args are lifetimes
    passMgr.add(createPromoteMemoryToRegisterPass());

    if (cl::DisablePatchOpt == false)
    {
        AddOptimizationPasses(pContext, passMgr);
    }

    // Stop timer for optimization passes and restart timer for patching passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pOptTimer, false));
        passMgr.add(CreateStartStopTimer(pPatchTimer, true));
    }

    // Patch buffer operations (must be after optimizations)
    passMgr.add(CreatePatchBufferOp());
    passMgr.add(createInstructionCombiningPass(false));

    // Fully prepare the pipeline ABI (must be after optimizations)
    passMgr.add(CreatePatchPreparePipelineAbi(/* onlySetCallingConvs = */ false));

#if LLPC_BUILD_GFX10
    if (pContext->IsGraphics() && pContext->GetNggControl()->enableNgg)
    {
        // Stop timer for patching passes and restart timer for optimization passes.
        if (pPatchTimer != nullptr)
        {
            passMgr.add(CreateStartStopTimer(pPatchTimer, false));
            passMgr.add(CreateStartStopTimer(pOptTimer, true));
        }

        // Extra optimizations after NGG primitive shader creation
        passMgr.add(createAlwaysInlinerLegacyPass());
        passMgr.add(CreatePassDeadFuncRemove());
        passMgr.add(createGlobalDCEPass());
        passMgr.add(createPromoteMemoryToRegisterPass());
        passMgr.add(createAggressiveDCEPass());
        passMgr.add(createInstructionCombiningPass(false));
        passMgr.add(createCFGSimplificationPass());

        // Stop timer for optimization passes and restart timer for patching passes.
        if (pPatchTimer != nullptr)
        {
            passMgr.add(CreateStartStopTimer(pOptTimer, false));
            passMgr.add(CreateStartStopTimer(pPatchTimer, true));
        }
    }
#endif

    // Set up target features in shader entry-points.
#if LLPC_BUILD_GFX10
    // NOTE: Needs to be done after post-NGG function inlining, because LLVM refuses to inline something
    // with conflicting attributes. Attributes could conflict on GFX10 because PatchSetupTargetFeatures
    // adds a target feature to determine wave32 or wave64.
#endif
    passMgr.add(CreatePatchSetupTargetFeatures());

    // Include LLVM IR as a separate section in the ELF binary
    if (cl::IncludeLlvmIr || pContext->GetPipelineContext()->GetPipelineOptions()->includeIr)
    {
        passMgr.add(CreatePatchLlvmIrInclusion());
    }

    // Stop timer for patching passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pPatchTimer, false));
    }

    // Dump the result
    if (EnableOuts())
    {
        passMgr.add(createPrintModulePass(outs(),
                    "===============================================================================\n"
                    "// LLPC pipeline patching results\n"));
    }
}

// =====================================================================================================================
// Add optimization passes to pass manager
void Patch::AddOptimizationPasses(
    Context*              pContext, // [in] LLPC context
    legacy::PassManager&  passMgr)  // [in/out] Pass manager to add passes to
{
    // Set up standard optimization passes.
    if (cl::UseLlvmOpt == false)
    {
        uint32_t optLevel = 3;
        bool expensiveCombines = false;
        bool disableGvnLoadPre = true;

        passMgr.add(createForceFunctionAttrsLegacyPass());
        passMgr.add(createIPSCCPPass());
        passMgr.add(createCalledValuePropagationPass());
        passMgr.add(createGlobalOptimizerPass());
        passMgr.add(createPromoteMemoryToRegisterPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createSROAPass());
        passMgr.add(createEarlyCSEPass(true));
        passMgr.add(createSpeculativeExecutionIfHasBranchDivergencePass());
        passMgr.add(createCorrelatedValuePropagationPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createAggressiveInstCombinerPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createReassociatePass());
        passMgr.add(createLoopRotatePass());
        passMgr.add(createLICMPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(createIndVarSimplifyPass());
        passMgr.add(createLoopIdiomPass());
        passMgr.add(createLoopDeletionPass());
        passMgr.add(createSimpleLoopUnrollPass(optLevel));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createScalarizerPass());
        passMgr.add(CreatePatchLoadScalarizer());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createMergedLoadStoreMotionPass());
        passMgr.add(createGVNPass(disableGvnLoadPre));
        passMgr.add(createSCCPPass());
        passMgr.add(createBitTrackingDCEPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createCorrelatedValuePropagationPass());
        passMgr.add(createAggressiveDCEPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createFloat2IntPass());
        passMgr.add(createLoopRotatePass());
        passMgr.add(createCFGSimplificationPass(1, true, true, false, true));
        passMgr.add(CreatePatchPeepholeOpt(true));
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createLoopUnrollPass(optLevel));
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(createLICMPass());
        passMgr.add(createStripDeadPrototypesPass());
        passMgr.add(createGlobalDCEPass());
        passMgr.add(createConstantMergePass());
        passMgr.add(createLoopSinkPass());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createDivRemPairsPass());
        passMgr.add(createCFGSimplificationPass());
    }
    else
    {
        PassManagerBuilder passBuilder;
        passBuilder.OptLevel = 3; // -O3
        passBuilder.DisableGVNLoadPRE = true;
        passBuilder.DivergentTarget = true;

        passBuilder.addExtension(PassManagerBuilder::EP_Peephole,
                                 [](const PassManagerBuilder&, legacy::PassManagerBase& passMgr)
                                 {
                                     passMgr.add(CreatePatchPeepholeOpt());
                                     passMgr.add(createInstSimplifyLegacyPass());
                                 });
        passBuilder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd,
            [](const PassManagerBuilder&, legacy::PassManagerBase& passMgr)
            {
                // We run our peephole pass just before the scalarizer to ensure that our simplification optimizations
                // are performed before the scalarizer. One important case this helps with is when you have bit casts
                // whose source is a PHI - we want to make sure that the PHI does not have an i8 type before the
                // scalarizer is called, otherwise a different kind of PHI mess is generated.
                passMgr.add(CreatePatchPeepholeOpt(true));

                // Run the scalarizer as it helps our register pressure in the backend significantly. The scalarizer
                // allows us to much more easily identify dead parts of vectors that we do not need to do any
                // computation for.
                passMgr.add(createScalarizerPass());

                // We add an extra inst simplify here to make sure that dead PHI nodes that are easily identified post
                // running the scalarizer can be folded away before instruction combining tries to re-create them.
                passMgr.add(createInstSimplifyLegacyPass());
            });

        passBuilder.populateModulePassManager(passMgr);
    }
}

// =====================================================================================================================
// Initializes the pass according to the specified module.
//
// NOTE: This function should be called at the beginning of "runOnModule()".
void Patch::Init(
    Module* pModule) // [in] LLVM module
{
    m_pModule  = pModule;
    m_pContext = static_cast<Context*>(&m_pModule->getContext());
    m_shaderStage = ShaderStageInvalid;
    m_pEntryPoint = nullptr;
}

// =====================================================================================================================
// Get or create global variable for LDS.
GlobalVariable* Patch::GetLdsVariable(
    Module* pModule)  // [in/out] Module to get or create LDS in
{
    auto pContext = static_cast<Context*>(&pModule->getContext());

    // See if this module already has LDS.
    auto pOldLds = pModule->getNamedValue("lds");
    if (pOldLds != nullptr)
    {
        // We already have LDS.
        return cast<GlobalVariable>(pOldLds);
    }
    // Now we can create LDS.
    // Construct LDS type: [ldsSize * i32], address space 3
    auto ldsSize = pContext->GetGpuProperty()->ldsSizePerCu;
    auto pLdsTy = ArrayType::get(pContext->Int32Ty(), ldsSize / sizeof(uint32_t));

    auto pLds = new GlobalVariable(*pModule,
                                   pLdsTy,
                                   false,
                                   GlobalValue::ExternalLinkage,
                                   nullptr,
                                   "lds",
                                   nullptr,
                                   GlobalValue::NotThreadLocal,
                                   ADDR_SPACE_LOCAL);
    pLds->setAlignment(MaybeAlign(sizeof(uint32_t)));
    return pLds;
}

} // Llpc
<commit_msg>Cleanup inlcludes in llpcPatch<commit_after>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  llpcPatch.cpp
 * @brief LLPC source file: contains implementation of class Llpc::Patch.
 ***********************************************************************************************************************
 */
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Scalar/InstSimplifyPass.h"
#include "llvm/Transforms/Scalar/Scalarizer.h"
#include "llvm/Transforms/Utils.h"
#include "llpcBuilder.h"
#include "llpcContext.h"
#include "llpcInternal.h"
#include "llpcPassManager.h"
#include "llpcPatch.h"
#include "llpcPatchCheckShaderCache.h"
#include "SPIRVInternal.h"

#define DEBUG_TYPE "llpc-patch"

using namespace llvm;

namespace llvm
{

namespace cl
{

// -disable-patch-opt: disable optimization for LLVM patching
opt<bool> DisablePatchOpt("disable-patch-opt", desc("Disable optimization for LLVM patching"));

// -include-llvm-ir: include LLVM IR as a separate section in the ELF binary
opt<bool> IncludeLlvmIr("include-llvm-ir",
                        desc("Include LLVM IR as a separate section in the ELF binary"),
                        init(false));

// -use-llvm-opt: Use LLVM's standard optimization set instead of the curated optimization set
opt<bool> UseLlvmOpt("use-llvm-opt",
                     desc("Use LLVM's standard optimization set instead of the curated optimization set"),
                     init(false));

} // cl

} // llvm

namespace Llpc
{

// =====================================================================================================================
// Add whole-pipeline patch passes to pass manager
void Patch::AddPasses(
    Context*              pContext,      // [in] LLPC context
    legacy::PassManager&  passMgr,       // [in/out] Pass manager to add passes to
    llvm::Timer*          pPatchTimer,   // [in] Timer to time patch passes with, nullptr if not timing
    llvm::Timer*          pOptTimer,     // [in] Timer to time LLVM optimization passes with, nullptr if not timing
    std::function<uint32_t(const Module*, uint32_t, ArrayRef<ArrayRef<uint8_t>>)>
                          checkShaderCacheFunc)
                                         // Callback function to check shader cache
{
    // Start timer for patching passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pPatchTimer, true));
    }

    // If using BuilderRecorder rather than BuilderImpl, replay the Builder calls now
    auto pBuilderReplayer = pContext->GetBuilder()->CreateBuilderReplayer();
    if (pBuilderReplayer != nullptr)
    {
        passMgr.add(pBuilderReplayer);
    }

    if (EnableOuts())
    {
        passMgr.add(createPrintModulePass(outs(),
                    "===============================================================================\n"
                    "// LLPC pipeline before-patching results\n"));
    }

    // Build null fragment shader if necessary
    passMgr.add(CreatePatchNullFragShader());

    // Patch resource collecting, remove inactive resources (should be the first preliminary pass)
    passMgr.add(CreatePatchResourceCollect());

    // Generate copy shader if necessary.
    passMgr.add(CreatePatchCopyShader());

    // Patch entry-point mutation (should be done before external library link)
    passMgr.add(CreatePatchEntryPointMutate());

    // Patch push constant loading (should be done before external library link)
    passMgr.add(CreatePatchPushConstOp());

    // Function inlining and remove dead functions after it
    passMgr.add(createAlwaysInlinerLegacyPass());
    passMgr.add(CreatePassDeadFuncRemove());

    // Patch input import and output export operations
    passMgr.add(CreatePatchInOutImportExport());

    // Patch descriptor load operations
    passMgr.add(CreatePatchDescriptorLoad());

    // Prior to general optimization, do function inlining and dead function removal once again
    passMgr.add(createAlwaysInlinerLegacyPass());
    passMgr.add(CreatePassDeadFuncRemove());

    // Check shader cache
    auto pCheckShaderCachePass = CreatePatchCheckShaderCache();
    passMgr.add(pCheckShaderCachePass);
    pCheckShaderCachePass->SetCallbackFunction(checkShaderCacheFunc);

    // Stop timer for patching passes and start timer for optimization passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pPatchTimer, false));
        passMgr.add(CreateStartStopTimer(pOptTimer, true));
    }

    // Prepare pipeline ABI but only set the calling conventions to AMDGPU ones for now.
    passMgr.add(CreatePatchPreparePipelineAbi(/* onlySetCallingConvs = */true));

    // Add some optimization passes

    // Need to run a first promote mem 2 reg to remove alloca's whose only args are lifetimes
    passMgr.add(createPromoteMemoryToRegisterPass());

    if (cl::DisablePatchOpt == false)
    {
        AddOptimizationPasses(pContext, passMgr);
    }

    // Stop timer for optimization passes and restart timer for patching passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pOptTimer, false));
        passMgr.add(CreateStartStopTimer(pPatchTimer, true));
    }

    // Patch buffer operations (must be after optimizations)
    passMgr.add(CreatePatchBufferOp());
    passMgr.add(createInstructionCombiningPass(false));

    // Fully prepare the pipeline ABI (must be after optimizations)
    passMgr.add(CreatePatchPreparePipelineAbi(/* onlySetCallingConvs = */ false));

#if LLPC_BUILD_GFX10
    if (pContext->IsGraphics() && pContext->GetNggControl()->enableNgg)
    {
        // Stop timer for patching passes and restart timer for optimization passes.
        if (pPatchTimer != nullptr)
        {
            passMgr.add(CreateStartStopTimer(pPatchTimer, false));
            passMgr.add(CreateStartStopTimer(pOptTimer, true));
        }

        // Extra optimizations after NGG primitive shader creation
        passMgr.add(createAlwaysInlinerLegacyPass());
        passMgr.add(CreatePassDeadFuncRemove());
        passMgr.add(createGlobalDCEPass());
        passMgr.add(createPromoteMemoryToRegisterPass());
        passMgr.add(createAggressiveDCEPass());
        passMgr.add(createInstructionCombiningPass(false));
        passMgr.add(createCFGSimplificationPass());

        // Stop timer for optimization passes and restart timer for patching passes.
        if (pPatchTimer != nullptr)
        {
            passMgr.add(CreateStartStopTimer(pOptTimer, false));
            passMgr.add(CreateStartStopTimer(pPatchTimer, true));
        }
    }
#endif

    // Set up target features in shader entry-points.
#if LLPC_BUILD_GFX10
    // NOTE: Needs to be done after post-NGG function inlining, because LLVM refuses to inline something
    // with conflicting attributes. Attributes could conflict on GFX10 because PatchSetupTargetFeatures
    // adds a target feature to determine wave32 or wave64.
#endif
    passMgr.add(CreatePatchSetupTargetFeatures());

    // Include LLVM IR as a separate section in the ELF binary
    if (cl::IncludeLlvmIr || pContext->GetPipelineContext()->GetPipelineOptions()->includeIr)
    {
        passMgr.add(CreatePatchLlvmIrInclusion());
    }

    // Stop timer for patching passes.
    if (pPatchTimer != nullptr)
    {
        passMgr.add(CreateStartStopTimer(pPatchTimer, false));
    }

    // Dump the result
    if (EnableOuts())
    {
        passMgr.add(createPrintModulePass(outs(),
                    "===============================================================================\n"
                    "// LLPC pipeline patching results\n"));
    }
}

// =====================================================================================================================
// Add optimization passes to pass manager
void Patch::AddOptimizationPasses(
    Context*              pContext, // [in] LLPC context
    legacy::PassManager&  passMgr)  // [in/out] Pass manager to add passes to
{
    // Set up standard optimization passes.
    if (cl::UseLlvmOpt == false)
    {
        uint32_t optLevel = 3;
        bool expensiveCombines = false;
        bool disableGvnLoadPre = true;

        passMgr.add(createForceFunctionAttrsLegacyPass());
        passMgr.add(createIPSCCPPass());
        passMgr.add(createCalledValuePropagationPass());
        passMgr.add(createGlobalOptimizerPass());
        passMgr.add(createPromoteMemoryToRegisterPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createSROAPass());
        passMgr.add(createEarlyCSEPass(true));
        passMgr.add(createSpeculativeExecutionIfHasBranchDivergencePass());
        passMgr.add(createCorrelatedValuePropagationPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createAggressiveInstCombinerPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createReassociatePass());
        passMgr.add(createLoopRotatePass());
        passMgr.add(createLICMPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(createIndVarSimplifyPass());
        passMgr.add(createLoopIdiomPass());
        passMgr.add(createLoopDeletionPass());
        passMgr.add(createSimpleLoopUnrollPass(optLevel));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createScalarizerPass());
        passMgr.add(CreatePatchLoadScalarizer());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createMergedLoadStoreMotionPass());
        passMgr.add(createGVNPass(disableGvnLoadPre));
        passMgr.add(createSCCPPass());
        passMgr.add(createBitTrackingDCEPass());
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(CreatePatchPeepholeOpt());
        passMgr.add(createCorrelatedValuePropagationPass());
        passMgr.add(createAggressiveDCEPass());
        passMgr.add(createCFGSimplificationPass());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createFloat2IntPass());
        passMgr.add(createLoopRotatePass());
        passMgr.add(createCFGSimplificationPass(1, true, true, false, true));
        passMgr.add(CreatePatchPeepholeOpt(true));
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createLoopUnrollPass(optLevel));
        passMgr.add(createInstructionCombiningPass(expensiveCombines));
        passMgr.add(createLICMPass());
        passMgr.add(createStripDeadPrototypesPass());
        passMgr.add(createGlobalDCEPass());
        passMgr.add(createConstantMergePass());
        passMgr.add(createLoopSinkPass());
        passMgr.add(createInstSimplifyLegacyPass());
        passMgr.add(createDivRemPairsPass());
        passMgr.add(createCFGSimplificationPass());
    }
    else
    {
        PassManagerBuilder passBuilder;
        passBuilder.OptLevel = 3; // -O3
        passBuilder.DisableGVNLoadPRE = true;
        passBuilder.DivergentTarget = true;

        passBuilder.addExtension(PassManagerBuilder::EP_Peephole,
                                 [](const PassManagerBuilder&, legacy::PassManagerBase& passMgr)
                                 {
                                     passMgr.add(CreatePatchPeepholeOpt());
                                     passMgr.add(createInstSimplifyLegacyPass());
                                 });
        passBuilder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd,
            [](const PassManagerBuilder&, legacy::PassManagerBase& passMgr)
            {
                // We run our peephole pass just before the scalarizer to ensure that our simplification optimizations
                // are performed before the scalarizer. One important case this helps with is when you have bit casts
                // whose source is a PHI - we want to make sure that the PHI does not have an i8 type before the
                // scalarizer is called, otherwise a different kind of PHI mess is generated.
                passMgr.add(CreatePatchPeepholeOpt(true));

                // Run the scalarizer as it helps our register pressure in the backend significantly. The scalarizer
                // allows us to much more easily identify dead parts of vectors that we do not need to do any
                // computation for.
                passMgr.add(createScalarizerPass());

                // We add an extra inst simplify here to make sure that dead PHI nodes that are easily identified post
                // running the scalarizer can be folded away before instruction combining tries to re-create them.
                passMgr.add(createInstSimplifyLegacyPass());
            });

        passBuilder.populateModulePassManager(passMgr);
    }
}

// =====================================================================================================================
// Initializes the pass according to the specified module.
//
// NOTE: This function should be called at the beginning of "runOnModule()".
void Patch::Init(
    Module* pModule) // [in] LLVM module
{
    m_pModule  = pModule;
    m_pContext = static_cast<Context*>(&m_pModule->getContext());
    m_shaderStage = ShaderStageInvalid;
    m_pEntryPoint = nullptr;
}

// =====================================================================================================================
// Get or create global variable for LDS.
GlobalVariable* Patch::GetLdsVariable(
    Module* pModule)  // [in/out] Module to get or create LDS in
{
    auto pContext = static_cast<Context*>(&pModule->getContext());

    // See if this module already has LDS.
    auto pOldLds = pModule->getNamedValue("lds");
    if (pOldLds != nullptr)
    {
        // We already have LDS.
        return cast<GlobalVariable>(pOldLds);
    }
    // Now we can create LDS.
    // Construct LDS type: [ldsSize * i32], address space 3
    auto ldsSize = pContext->GetGpuProperty()->ldsSizePerCu;
    auto pLdsTy = ArrayType::get(pContext->Int32Ty(), ldsSize / sizeof(uint32_t));

    auto pLds = new GlobalVariable(*pModule,
                                   pLdsTy,
                                   false,
                                   GlobalValue::ExternalLinkage,
                                   nullptr,
                                   "lds",
                                   nullptr,
                                   GlobalValue::NotThreadLocal,
                                   ADDR_SPACE_LOCAL);
    pLds->setAlignment(MaybeAlign(sizeof(uint32_t)));
    return pLds;
}

} // Llpc
<|endoftext|>


<commit_before>#include <iostream>

#include "coverart/HTTPFetch.h"
#include "coverart/CoverArt.h"

int main(int /*argc*/, const char */*argv*/[])
{
	try
	{
		CoverArtArchive::CCoverArt Art("test");
		CoverArtArchive::CReleaseInfo ReleaseInfo=Art.ReleaseInfo("189d7863-a23c-49d9-ae7e-031b413b2805");
		std::cout << ReleaseInfo << std::endl;

/*
		std::vector<unsigned char> Image=Art.FetchFront("189d7863-a23c-49d9-ae7e-031b413b2805");
		std::cout << "Front has size " << Image.size() << std::endl;

		Image=Art.FetchBack("189d7863-a23c-49d9-ae7e-031b413b2805");
		std::cout << "Back has size " << Image.size() << std::endl;

		Image=Art.FetchImage("189d7863-a23c-49d9-ae7e-031b413b2805","832154846");
		std::cout << "Image has size " << Image.size() << std::endl;

		Image=Art.FetchImage("189d7863-a23c-49d9-ae7e-031b413b2805","832154846",CoverArtArchive::CCoverArt::eSize_250);
		std::cout << "Image has size " << Image.size() << std::endl;

		Image=Art.FetchImage("189d7863-a23c-49d9-ae7e-031b413b2805","832154846",CoverArtArchive::CCoverArt::eSize_500);
		std::cout << "Image has size " << Image.size() << std::endl;
*/
	}

	catch (CoverArtArchive::CExceptionBase e)
	{
		std::cout << "Exception: " << e.what() << std::endl;
	}

  return 0;
}
<commit_msg>More complete test program<commit_after>#include <iostream>

#include "coverart/HTTPFetch.h"
#include "coverart/CoverArt.h"

int main(int /*argc*/, const char */*argv*/[])
{
	try
	{
		CoverArtArchive::CCoverArt Art("test");
		CoverArtArchive::CReleaseInfo ReleaseInfo=Art.ReleaseInfo("189d7863-a23c-49d9-ae7e-031b413b2805");
		std::cout << ReleaseInfo << std::endl;

		std::vector<unsigned char> Image=Art.FetchFront("189d7863-a23c-49d9-ae7e-031b413b2805");
		std::cout << "Front has size " << Image.size() << std::endl;

		Image=Art.FetchBack("189d7863-a23c-49d9-ae7e-031b413b2805");
		std::cout << "Back has size " << Image.size() << std::endl;

		Image=Art.FetchImage("189d7863-a23c-49d9-ae7e-031b413b2805","832154846");
		std::cout << "Image has size " << Image.size() << std::endl;

		Image=Art.FetchImage("189d7863-a23c-49d9-ae7e-031b413b2805","832154846",CoverArtArchive::CCoverArt::eSize_250);
		std::cout << "Image has size " << Image.size() << std::endl;

		Image=Art.FetchImage("189d7863-a23c-49d9-ae7e-031b413b2805","832154846",CoverArtArchive::CCoverArt::eSize_500);
		std::cout << "Image has size " << Image.size() << std::endl;
	}

	catch (CoverArtArchive::CExceptionBase e)
	{
		std::cout << "Exception: " << e.what() << std::endl;
	}

  return 0;
}
<|endoftext|>


<commit_before>/*
  NGL - C++ cross-platform framework for OpenGL based applications
  Copyright (C) 2000-2003 NGL Team

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "nui.h"
#include "nglKernel.h"
#ifndef _MINUI3_
#include "nglWindow.h"
#endif
#include "ngl_unix.h"
#include <signal.h>
#include <locale.h>

using namespace std;

const nglChar* gpKernelErrorTable[] =
{
/*  0 */ _T("No error"),
  NULL
};

/*
 * Life cycle
 */

nglKernel::nglKernel()
: mKernelEventSink(this)
{
  Init();

/*
  // If we're attached to a tty, save its settings for segfault handler
  if (isatty(STDIN_FILENO)) tcgetattr (STDIN_FILENO, &mTermInfo);
*/
}

nglKernel::~nglKernel()
{
/*
  if (isatty(STDIN_FILENO)) tcsetattr (STDIN_FILENO, TCSANOW, &mTermInfo);
*/
  Exit(0);

}

/*
 * Event handling (stubs rather than pure virtual methods)
 */

void nglKernel::AddEvent (nglEvent* pEvent)
{
}

void nglKernel::DelEvent (nglEvent* pEvent)
{
}

void nglKernel::AddTimer (nglTimer* pTimer)
{
}

void nglKernel::DelTimer (nglTimer* pTimer)
{
}

#ifndef _MINUI3_

/*
 * Clipboard
 */

//changed from nglString nglKernel::GetClipboard() to this, according to nglKernel.h
void nglKernel::GetClipboard(nglString& rClipboard)
{
  nglString result(_T("*clipboard code not implemented*"));

  // FIXME
  //now returns void, according to nglKernel.h
  //return result;
}

bool nglKernel::SetClipboard(const nglString& rString)
{
  // FIXME
  return false;
}

void* nglKernel::GetDisplay()
{
  return NULL;
}

void nglKernel::AddWindow (class nglWindow* pWin)
{
}

void nglKernel::DelWindow (class nglWindow* pWin)
{
}

#endif // ifndef _MINUI3_

/*
 * Internals (generic kernel setup)
 */

bool nglKernel::SysInit()
{
  int signals[] = {
    SIGSEGV,
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGPIPE,
    SIGTERM,
    -1
  };
  int sig;

  for (sig = 0; signals[sig] != -1; sig++)
    CatchSignal (signals[sig], OnSignal);

  // Set locale (for strtoup(), time/date formatting and so on)
  setlocale (LC_ALL, "");

  return true;
}

void nglKernel::CatchSignal (int Signal, void (*pHandler)(int))
{
  struct sigaction act;

  act.sa_handler = pHandler;
  sigemptyset (&act.sa_mask);
  act.sa_flags = (Signal == SIGCHLD) ? SA_NOCLDSTOP : 0;
  sigaction (Signal, &act, NULL);
}

void nglKernel::OnSignal(int Signal) /* static method */
{
  switch (Signal)
  {
    case SIGSEGV:
    {
/*
      if (isatty(STDIN_FILENO) && (crashcount < 1))
        tcsetattr (STDIN_FILENO, TCSANOW, &App->mTermInfo);
*/
      NGL_DEBUG( NGL_LOG(_T("kernel"), NGL_LOG_ERROR, _T("** Segmentation fault\n")); )
      exit(2);
    }

    case SIGHUP:
    case SIGINT:
    case SIGQUIT:
    case SIGPIPE:
    case SIGTERM:
    {
      NGL_DEBUG( NGL_LOG(_T("kernel"), NGL_LOG_ERROR, _T("** Caught signal %d\n"), Signal); )
#ifndef _MINUI3_
      App->Quit(1);
#else
      exit(1);
#endif
    }
  }
}

void nglKernel::OnEvent(uint Flags)
{
}

#ifndef _MINUI3_
void nglKernel::EnterModalState()
{
}

void nglKernel::ExitModalState()
{
}
#endif

void nglKernel::NonBlockingHeartBeat()
{
}
<commit_msg>fixed libcrypt and libcurl global init w/ multithreading<commit_after>/*
  NGL - C++ cross-platform framework for OpenGL based applications
  Copyright (C) 2000-2003 NGL Team

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "nui.h"
#include "nglKernel.h"
#ifndef _MINUI3_
#include "nglWindow.h"
#endif
#include "ngl_unix.h"
#include <signal.h>
#include <locale.h>

#include <gcrypt.h>
#include <curl/curl.h>
GCRY_THREAD_OPTION_PTHREAD_IMPL;

using namespace std;

const nglChar* gpKernelErrorTable[] =
{
/*  0 */ _T("No error"),
  NULL
};

/*
 * Life cycle
 */

nglKernel::nglKernel()
: mKernelEventSink(this)
{
  Init();

/*
  // If we're attached to a tty, save its settings for segfault handler
  if (isatty(STDIN_FILENO)) tcgetattr (STDIN_FILENO, &mTermInfo);
*/
}

nglKernel::~nglKernel()
{
/*
  if (isatty(STDIN_FILENO)) tcsetattr (STDIN_FILENO, TCSANOW, &mTermInfo);
*/
  Exit(0);

}

/*
 * Event handling (stubs rather than pure virtual methods)
 */

void nglKernel::AddEvent (nglEvent* pEvent)
{
}

void nglKernel::DelEvent (nglEvent* pEvent)
{
}

void nglKernel::AddTimer (nglTimer* pTimer)
{
}

void nglKernel::DelTimer (nglTimer* pTimer)
{
}

#ifndef _MINUI3_

/*
 * Clipboard
 */

//changed from nglString nglKernel::GetClipboard() to this, according to nglKernel.h
void nglKernel::GetClipboard(nglString& rClipboard)
{
  nglString result(_T("*clipboard code not implemented*"));

  // FIXME
  //now returns void, according to nglKernel.h
  //return result;
}

bool nglKernel::SetClipboard(const nglString& rString)
{
  // FIXME
  return false;
}

void* nglKernel::GetDisplay()
{
  return NULL;
}

void nglKernel::AddWindow (class nglWindow* pWin)
{
}

void nglKernel::DelWindow (class nglWindow* pWin)
{
}

#endif // ifndef _MINUI3_

/*
 * Internals (generic kernel setup)
 */

bool nglKernel::SysInit()
{
  int signals[] = {
    SIGSEGV,
    SIGHUP,
    SIGINT,
    SIGQUIT,
    //SIGPIPE,
    SIGTERM,
    -1
  };
  int sig;

  for (sig = 0; signals[sig] != -1; sig++)
    CatchSignal (signals[sig], OnSignal);

  // Set locale (for strtoup(), time/date formatting and so on)
  setlocale (LC_ALL, "");

  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
  curl_global_init(CURL_GLOBAL_ALL);
  return true;
}

void nglKernel::CatchSignal (int Signal, void (*pHandler)(int))
{
  struct sigaction act;

  act.sa_handler = pHandler;
  sigemptyset (&act.sa_mask);
  act.sa_flags = (Signal == SIGCHLD) ? SA_NOCLDSTOP : 0;
  sigaction (Signal, &act, NULL);
}

void nglKernel::OnSignal(int Signal) /* static method */
{
  switch (Signal)
  {
    case SIGSEGV:
    {
/*
      if (isatty(STDIN_FILENO) && (crashcount < 1))
        tcsetattr (STDIN_FILENO, TCSANOW, &App->mTermInfo);
*/
      NGL_DEBUG( NGL_LOG(_T("kernel"), NGL_LOG_ERROR, _T("** Segmentation fault\n")); )
      exit(2);
    }

    case SIGHUP:
    case SIGINT:
    case SIGQUIT:
    case SIGPIPE:
    case SIGTERM:
    {
      NGL_DEBUG( NGL_LOG(_T("kernel"), NGL_LOG_ERROR, _T("** Caught signal %d\n"), Signal); )
#ifndef _MINUI3_
      App->Quit(1);
#else
      exit(1);
#endif
    }
  }
}

void nglKernel::OnEvent(uint Flags)
{
}

#ifndef _MINUI3_
void nglKernel::EnterModalState()
{
}

void nglKernel::ExitModalState()
{
}
#endif

void nglKernel::NonBlockingHeartBeat()
{
}
<|endoftext|>


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

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

 ======================================================================*/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "AutoPilotPlugin.h"

AutoPilotPlugin::AutoPilotPlugin(UASInterface* uas, QObject* parent) :
    QObject(parent),
    _uas(uas),
    _pluginReady(false)
{
    Q_ASSERT(_uas);
}

bool AutoPilotPlugin::factExists(FactSystem::Provider_t provider, int componentId, const QString& name)
{
    switch (provider) {
        case FactSystem::ParameterProvider:
            return getParameterLoader()->factExists(componentId, name);

        // Other providers will go here once they come online
    }

    Q_ASSERT(false);
    return false;
}

Fact* AutoPilotPlugin::getFact(FactSystem::Provider_t provider, int componentId, const QString& name)
{
    switch (provider) {
        case FactSystem::ParameterProvider:
            return getParameterLoader()->getFact(componentId, name);

        // Other providers will go here once they come online
    }

    Q_ASSERT(false);
    return false;
}
<commit_msg>Oopsie!<commit_after>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

 ======================================================================*/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "AutoPilotPlugin.h"

AutoPilotPlugin::AutoPilotPlugin(UASInterface* uas, QObject* parent) :
    QObject(parent),
    _uas(uas),
    _pluginReady(false)
{
    Q_ASSERT(_uas);
}

bool AutoPilotPlugin::factExists(FactSystem::Provider_t provider, int componentId, const QString& name)
{
    switch (provider) {
        case FactSystem::ParameterProvider:
            return getParameterLoader()->factExists(componentId, name);

        // Other providers will go here once they come online
    }

    Q_ASSERT(false);
    return false;
}

Fact* AutoPilotPlugin::getFact(FactSystem::Provider_t provider, int componentId, const QString& name)
{
    switch (provider) {
        case FactSystem::ParameterProvider:
            return getParameterLoader()->getFact(componentId, name);

        // Other providers will go here once they come online
    }

    Q_ASSERT(false);
    return NULL;
}
<|endoftext|>


<commit_before>// main.cc            see license.txt for copyright and terms of use
// entry-point module for a program that parses C++

#include <iostream.h>     // cout
#include <stdlib.h>       // exit, getenv

#include "trace.h"        // traceAddSys
#include "parssppt.h"     // ParseTreeAndTokens, treeMain
#include "srcloc.h"       // SourceLocManager
#include "ckheap.h"       // malloc_stats
#include "cc_env.h"       // Env
#include "cc_ast.h"       // C++ AST (r)
#include "cc_lang.h"      // CCLang
#include "parsetables.h"  // ParseTables
#include "cc_print.h"     // PrintEnv
#include "cc.gr.gen.h"    // CCParse
#include "nonport.h"      // getMilliseconds
#include "ptreenode.h"    // PTreeNode
#include "ptreeact.h"     // ParseTreeLexer, ParseTreeActions
#include "sprint.h"       // structurePrint
#include "strtokp.h"      // StrtokParse
#include "smregexp.h"     // regexpMatch
#include "cc_elaborate.h" // ElabVisitor

// little check: is it true that only global declarators
// ever have Declarator::type != Declarator::var->type?
// .. no, because it's true for class members too ..
// .. it's also true of arrays declared [] but then inited ..
// .. finally, it's true of parameters whose types get
//    normalized as per cppstd 8.3.5 para 3; I didn't include
//    that case below because there's no easy way to test for it ..
class DeclTypeChecker : public ASTVisitor {
public:
  int instances;

public:
  DeclTypeChecker() : instances(0) {}
  virtual bool visitDeclarator(Declarator *obj);
};

bool DeclTypeChecker::visitDeclarator(Declarator *obj)
{
  if (obj->type != obj->var->type &&
      !(obj->var->flags & (DF_GLOBAL | DF_MEMBER)) &&
      !obj->type->isArrayType()) {
    instances++;
    cout << toString(obj->var->loc) << ": " << obj->var->name
         << " has type != var->type, but is not global or member or array\n";
  }
  return true;
}

// this scans the AST for E_variables, and writes down the locations
// to which they resolved; it's helpful for writing tests of name and
// overload resolution
class NameChecker : public ASTVisitor {
public:
  // accumulates the results
  stringBuilder sb;

public:
  NameChecker() {}
  virtual ~NameChecker() {}    // gcc idiocy

  virtual bool visitExpression(Expression *obj)
  {
    Variable *v = NULL;
    if (obj->isE_variable()) {
      v = obj->asE_variable()->var;
    }
    else if (obj->isE_fieldAcc()) {
      v = obj->asE_fieldAcc()->field;
    }

    // this output format is designed to minimize the effect of
    // changes to unrelated details
    if (v
        && 0!=strcmp("__testOverload", v->name)
        && 0!=strcmp("dummy",          v->name)
        && 0!=strcmp("__other",        v->name) // "__other": for inserted elaboration code
        && 0!=strcmp("this",           v->name) // dsw: not sure why "this" is showing up
        && 0!=strcmp("operator=",      v->name) // an implicitly defined member of every class
        && v->name[0]!='~'                      // don't print dtors
        ) {
      sb << " " << v->name << "=" << sourceLocManager->getLine(v->loc);
    }

    return true;
  }
};

void if_malloc_stats()
{
  if (tracingSys("malloc_stats")) {
    malloc_stats();
  }
}

void doit(int argc, char **argv)
{
  traceAddSys("progress");
  //traceAddSys("parse-tree");

  if_malloc_stats();

  SourceLocManager mgr;

  // string table for storing parse tree identifiers
  StringTable strTable;

  // parsing language options
  CCLang lang;
  lang.ANSI_Cplusplus();

  // --------------- parse --------------
  TranslationUnit *unit;
  {
    char const *inputFname = processArgs
      (argc, argv,
       "\n"
       "  general behavior flags:\n"
       "    c_lang             use C language rules (default is C++)\n"
       "    nohashline         ignore #line when reporting locations\n"
       "    doOverload         do named function overload resolution\n"
       "    doOperatorOverload do operator overload resolution\n"
       "\n"
       "  options to stop after a certain stage:\n"
       "    stopAfterParse     stop after parsing\n"
       "    stopAfterTCheck    stop after typechecking\n"
       "    stopAfterElab      stop after semantic elaboration\n"
       "\n"
       "  output options:\n"
       "    parseTree          make a parse tree and print that, only\n"
       "    printAST           print AST after parsing\n"
       "    printTypedAST      print AST with type info\n"
       "    printElabAST       print AST after semantic elaboration\n"
       "    prettyPrint        echo input as pretty-printed (but sometimes invalid) C++\n"
       "\n"
       "  debugging output:\n"
       "    malloc_stats       print malloc stats every so often\n"
       "    env                print as variables are added to the environment\n"
       "    error              print as errors are accumulated\n"
       "    overload           print details of overload resolution\n"
       "\n"
       "  (grep in source for \"trace\" to find more obscure flags)\n"
       "");

    if (tracingSys("printAsML")) {
      Type::printAsML = true;
    }

    if (tracingSys("nohashline")) {
      sourceLocManager->useHashLines = false;
    }

    if (tracingSys("c_lang")) {
      lang.ANSI_C();
    }

    SemanticValue treeTop;
    ParseTreeAndTokens tree(lang, treeTop, strTable, inputFname);

    // grab the lexer so we can check it for errors (damn this
    // 'tree' thing is stupid..)
    Lexer *lexer = dynamic_cast<Lexer*>(tree.lexer);
    xassert(lexer);

    CCParse *parseContext = new CCParse(strTable, lang);
    tree.userAct = parseContext;

    traceProgress(2) << "building parse tables from internal data\n";
    ParseTables *tables = parseContext->makeTables();
    tree.tables = tables;

    maybeUseTrivialActions(tree);

    if (tracingSys("parseTree")) {
      // make some helpful aliases
      LexerInterface *underLexer = tree.lexer;
      UserActions *underAct = parseContext;

      // replace the lexer and parser with parse-tree-building versions
      tree.lexer = new ParseTreeLexer(underLexer, underAct);
      tree.userAct = new ParseTreeActions(underAct, tables);

      // 'underLexer' and 'tree.userAct' will be leaked.. oh well
    }

    if (!toplevelParse(tree, inputFname)) {
      exit(2); // parse error
    }

    // check for parse errors detected by the context class
    if (parseContext->errors || lexer->errors) {
      exit(2);
    }

    traceProgress(2) << "final parse result: " << treeTop << endl;

    if (tracingSys("parseTree")) {
      // the 'treeTop' is actually a PTreeNode pointer; print the
      // tree and bail
      PTreeNode *ptn = (PTreeNode*)treeTop;
      ptn->printTree(cout, PTreeNode::PF_EXPAND);
      return;
    }

    // treeTop is a TranslationUnit pointer
    unit = (TranslationUnit*)treeTop;

    //unit->debugPrint(cout, 0);

    delete parseContext;
    delete tables;
  }

  checkHeap();

  // print abstract syntax tree
  if (tracingSys("printAST")) {
    unit->debugPrint(cout, 0);
  }

  if (unit) {     // when "-tr trivialActions" it's NULL...
    cout << "ambiguous nodes: " << numAmbiguousNodes(unit) << endl;
  }

  if (tracingSys("stopAfterParse")) {
    return;
  }

  // ---------------- typecheck -----------------
  BasicTypeFactory tfac;
  {

    traceProgress(2) << "type checking...\n";
    long tcheckStart = getMilliseconds();
    Env env(strTable, lang, tfac, unit);
    try {
      unit->tcheck(env);
    }
    catch (xBase &x) {
      // typically an assertion failure from the tchecker; catch it here
      // so we can print the errors, and something about the location
      env.errors.print(cout);
      cout << x << endl;
      cout << "Failure probably related to code near " << env.locStr() << endl;
      if (tracingSys("locstack")) {
        // print all the locations on the scope stack; this is sometimes
        // useful when the env.locStr refers to some template code that
        // was instantiated from somewhere else
        cout << env.locationStackString();
      }
      exit(4);
    }
    traceProgress() << "done type checking ("
                    << (getMilliseconds() - tcheckStart)
                    << " ms)\n";

    int numErrors = env.errors.numErrors();
    int numWarnings = env.errors.numWarnings();

    // do this now so that 'printTypedAST' will include CFG info
    #ifdef CFG_EXTENSION
    // A possible TODO is to do this right after each function is type
    // checked.  However, in the current design, that means physically
    // inserting code into Function::tcheck (ifdef'd of course).  A way
    // to do it better would be to have a general post-function-tcheck
    // interface that analyses could hook in to.  That could be augmented
    // by a parsing mode that parsed each function, analyzed it, and then
    // immediately discarded its AST.
    numErrors += computeUnitCFG(unit);
    #endif // CFG_EXTENSION

    // print abstract syntax tree annotated with types
    if (tracingSys("printTypedAST")) {
      unit->debugPrint(cout, 0);
    }

    // structural delta thing
    if (tracingSys("structure")) {
      structurePrint(unit);
    }

    if (tracingSys("secondTcheck")) {
      // this is useful to measure the cost of disambiguation, since
      // now the tree is entirely free of ambiguities
      traceProgress() << "beginning second tcheck...\n";
      Env env2(strTable, lang, tfac, unit);
      unit->tcheck(env2);
      traceProgress() << "end of second tcheck\n";
    }

    // print errors and warnings
    env.errors.print(cout);

    cout << "typechecking results:\n"
         << "  errors:   " << numErrors << "\n"
         << "  warnings: " << numWarnings << "\n";

    if (numErrors != 0) {
      exit(4);
    }

    // verify the tree now has no ambiguities
    if (unit && numAmbiguousNodes(unit) != 0) {
      cout << "UNEXPECTED: ambiguities remain after type checking!\n";
      if (tracingSys("mustBeUnambiguous")) {
        exit(2);
      }
    }

    // check an expected property of the annotated AST
    if (tracingSys("declTypeCheck") || getenv("declTypeCheck")) {
      DeclTypeChecker vis;
      unit->traverse(vis);
      cout << "instances of type != var->type: " << vis.instances << endl;
    }

    // lookup diagnostic
    if (env.collectLookupResults) {
      // scan AST
      NameChecker nc;
      nc.sb << "\"collectLookupResults";
      unit->traverse(nc);
      nc.sb << "\"";

      // compare to given text
      if (0==strcmp(env.collectLookupResults, nc.sb)) {
        // ok
      }
      else {
        cout << "collectLookupResults do not match:\n"
             << "  source: " << env.collectLookupResults << "\n"
             << "  tcheck: " << nc.sb << "\n"
             ;
        exit(4);
      }
    }

//      if (tracingSys("flattenTemplates")) {
//        traceProgress() << "dsw flatten...\n";
//        FlattenEnv env(cout);
//        unit->flatten(env);
//        traceProgress() << "dsw flatten... done\n";
//        cout << endl;
//      }

    if (tracingSys("stopAfterTCheck")) {
      return;
    }
  }

  // semantic elaboration
  if (lang.isCplusplus) {
    long start = getMilliseconds();

    ElabVisitor vis(strTable, tfac, unit);

    // if we are going to pretty print, then we need to retain defunct children
    if (tracingSys("prettyPrint")) {
      vis.cloneDefunctChildren = true;
    }

    unit->traverse(vis);

    traceProgress() << "done elaborating ("
                    << (getMilliseconds() - start)
                    << " ms)\n";

    // print abstract syntax tree annotated with types
    if (tracingSys("printElabAST")) {
      unit->debugPrint(cout, 0);
    }
    if (tracingSys("stopAfterElab")) {
      return;
    }
  }

  // dsw: pretty printing
  if (tracingSys("prettyPrint")) {
    cout << endl;
    traceProgress() << "dsw pretty print...\n";
    PrintEnv env(cout);
    cout << "---- START ----" << endl;
    cout << "// -*-c++-*-" << endl;
    unit->print(env);
    env.finish();
    cout << "---- STOP ----" << endl;
    traceProgress() << "dsw pretty print... done\n";
    cout << endl;
  }

  // test AST cloning
  if (tracingSys("testClone")) {
    TranslationUnit *u2 = unit->clone();

    if (tracingSys("cloneAST")) {
      cout << "------- cloned AST --------\n";
      u2->debugPrint(cout, 0);
    }

    if (tracingSys("cloneCheck")) {
      // dsw: I hope you intend that I should use the cloned TranslationUnit
      Env env3(strTable, lang, tfac, u2);
      u2->tcheck(env3);

      if (tracingSys("cloneTypedAST")) {
        cout << "------- cloned typed AST --------\n";
        u2->debugPrint(cout, 0);
      }

      if (tracingSys("clonePrint")) {
        PrintEnv penv(cout);
        cout << "---- cloned pretty print ----" << endl;
        u2->print(penv);
        penv.finish();
      }
    }
  }

  //traceProgress() << "cleaning up...\n";

  //malloc_stats();

  // delete the tree
  // (currently this doesn't do very much because FakeLists are
  // non-owning, so I won't pretend it does)
  //delete unit;

  strTable.clear();

  //checkHeap();
  //malloc_stats();
}

int main(int argc, char **argv)
{
  try {
    doit(argc, argv);
  }
  catch (xBase &x) {
    cout << x << endl;
    return 4;
  }

  //malloc_stats();

  return 0;
}
<commit_msg>minor change to handling of unhandled exceptions, in hopes that multitest won't silently allow assertion failures to count as "successfully identified bad C++"<commit_after>// main.cc            see license.txt for copyright and terms of use
// entry-point module for a program that parses C++

#include <iostream.h>     // cout
#include <stdlib.h>       // exit, getenv, abort

#include "trace.h"        // traceAddSys
#include "parssppt.h"     // ParseTreeAndTokens, treeMain
#include "srcloc.h"       // SourceLocManager
#include "ckheap.h"       // malloc_stats
#include "cc_env.h"       // Env
#include "cc_ast.h"       // C++ AST (r)
#include "cc_lang.h"      // CCLang
#include "parsetables.h"  // ParseTables
#include "cc_print.h"     // PrintEnv
#include "cc.gr.gen.h"    // CCParse
#include "nonport.h"      // getMilliseconds
#include "ptreenode.h"    // PTreeNode
#include "ptreeact.h"     // ParseTreeLexer, ParseTreeActions
#include "sprint.h"       // structurePrint
#include "strtokp.h"      // StrtokParse
#include "smregexp.h"     // regexpMatch
#include "cc_elaborate.h" // ElabVisitor

// little check: is it true that only global declarators
// ever have Declarator::type != Declarator::var->type?
// .. no, because it's true for class members too ..
// .. it's also true of arrays declared [] but then inited ..
// .. finally, it's true of parameters whose types get
//    normalized as per cppstd 8.3.5 para 3; I didn't include
//    that case below because there's no easy way to test for it ..
class DeclTypeChecker : public ASTVisitor {
public:
  int instances;

public:
  DeclTypeChecker() : instances(0) {}
  virtual bool visitDeclarator(Declarator *obj);
};

bool DeclTypeChecker::visitDeclarator(Declarator *obj)
{
  if (obj->type != obj->var->type &&
      !(obj->var->flags & (DF_GLOBAL | DF_MEMBER)) &&
      !obj->type->isArrayType()) {
    instances++;
    cout << toString(obj->var->loc) << ": " << obj->var->name
         << " has type != var->type, but is not global or member or array\n";
  }
  return true;
}

// this scans the AST for E_variables, and writes down the locations
// to which they resolved; it's helpful for writing tests of name and
// overload resolution
class NameChecker : public ASTVisitor {
public:
  // accumulates the results
  stringBuilder sb;

public:
  NameChecker() {}
  virtual ~NameChecker() {}    // gcc idiocy

  virtual bool visitExpression(Expression *obj)
  {
    Variable *v = NULL;
    if (obj->isE_variable()) {
      v = obj->asE_variable()->var;
    }
    else if (obj->isE_fieldAcc()) {
      v = obj->asE_fieldAcc()->field;
    }

    // this output format is designed to minimize the effect of
    // changes to unrelated details
    if (v
        && 0!=strcmp("__testOverload", v->name)
        && 0!=strcmp("dummy",          v->name)
        && 0!=strcmp("__other",        v->name) // "__other": for inserted elaboration code
        && 0!=strcmp("this",           v->name) // dsw: not sure why "this" is showing up
        && 0!=strcmp("operator=",      v->name) // an implicitly defined member of every class
        && v->name[0]!='~'                      // don't print dtors
        ) {
      sb << " " << v->name << "=" << sourceLocManager->getLine(v->loc);
    }

    return true;
  }
};

void if_malloc_stats()
{
  if (tracingSys("malloc_stats")) {
    malloc_stats();
  }
}

void doit(int argc, char **argv)
{
  traceAddSys("progress");
  //traceAddSys("parse-tree");

  if_malloc_stats();

  SourceLocManager mgr;

  // string table for storing parse tree identifiers
  StringTable strTable;

  // parsing language options
  CCLang lang;
  lang.ANSI_Cplusplus();

  // --------------- parse --------------
  TranslationUnit *unit;
  {
    char const *inputFname = processArgs
      (argc, argv,
       "\n"
       "  general behavior flags:\n"
       "    c_lang             use C language rules (default is C++)\n"
       "    nohashline         ignore #line when reporting locations\n"
       "    doOverload         do named function overload resolution\n"
       "    doOperatorOverload do operator overload resolution\n"
       "\n"
       "  options to stop after a certain stage:\n"
       "    stopAfterParse     stop after parsing\n"
       "    stopAfterTCheck    stop after typechecking\n"
       "    stopAfterElab      stop after semantic elaboration\n"
       "\n"
       "  output options:\n"
       "    parseTree          make a parse tree and print that, only\n"
       "    printAST           print AST after parsing\n"
       "    printTypedAST      print AST with type info\n"
       "    printElabAST       print AST after semantic elaboration\n"
       "    prettyPrint        echo input as pretty-printed (but sometimes invalid) C++\n"
       "\n"
       "  debugging output:\n"
       "    malloc_stats       print malloc stats every so often\n"
       "    env                print as variables are added to the environment\n"
       "    error              print as errors are accumulated\n"
       "    overload           print details of overload resolution\n"
       "\n"
       "  (grep in source for \"trace\" to find more obscure flags)\n"
       "");

    if (tracingSys("printAsML")) {
      Type::printAsML = true;
    }

    if (tracingSys("nohashline")) {
      sourceLocManager->useHashLines = false;
    }

    if (tracingSys("c_lang")) {
      lang.ANSI_C();
    }

    SemanticValue treeTop;
    ParseTreeAndTokens tree(lang, treeTop, strTable, inputFname);

    // grab the lexer so we can check it for errors (damn this
    // 'tree' thing is stupid..)
    Lexer *lexer = dynamic_cast<Lexer*>(tree.lexer);
    xassert(lexer);

    CCParse *parseContext = new CCParse(strTable, lang);
    tree.userAct = parseContext;

    traceProgress(2) << "building parse tables from internal data\n";
    ParseTables *tables = parseContext->makeTables();
    tree.tables = tables;

    maybeUseTrivialActions(tree);

    if (tracingSys("parseTree")) {
      // make some helpful aliases
      LexerInterface *underLexer = tree.lexer;
      UserActions *underAct = parseContext;

      // replace the lexer and parser with parse-tree-building versions
      tree.lexer = new ParseTreeLexer(underLexer, underAct);
      tree.userAct = new ParseTreeActions(underAct, tables);

      // 'underLexer' and 'tree.userAct' will be leaked.. oh well
    }

    if (!toplevelParse(tree, inputFname)) {
      exit(2); // parse error
    }

    // check for parse errors detected by the context class
    if (parseContext->errors || lexer->errors) {
      exit(2);
    }

    traceProgress(2) << "final parse result: " << treeTop << endl;

    if (tracingSys("parseTree")) {
      // the 'treeTop' is actually a PTreeNode pointer; print the
      // tree and bail
      PTreeNode *ptn = (PTreeNode*)treeTop;
      ptn->printTree(cout, PTreeNode::PF_EXPAND);
      return;
    }

    // treeTop is a TranslationUnit pointer
    unit = (TranslationUnit*)treeTop;

    //unit->debugPrint(cout, 0);

    delete parseContext;
    delete tables;
  }

  checkHeap();

  // print abstract syntax tree
  if (tracingSys("printAST")) {
    unit->debugPrint(cout, 0);
  }

  if (unit) {     // when "-tr trivialActions" it's NULL...
    cout << "ambiguous nodes: " << numAmbiguousNodes(unit) << endl;
  }

  if (tracingSys("stopAfterParse")) {
    return;
  }

  // ---------------- typecheck -----------------
  BasicTypeFactory tfac;
  {

    traceProgress(2) << "type checking...\n";
    long tcheckStart = getMilliseconds();
    Env env(strTable, lang, tfac, unit);
    try {
      unit->tcheck(env);
    }
    catch (xBase &x) {
      // typically an assertion failure from the tchecker; catch it here
      // so we can print the errors, and something about the location
      env.errors.print(cout);
      cout << x << endl;
      cout << "Failure probably related to code near " << env.locStr() << endl;
      if (tracingSys("locstack")) {
        // print all the locations on the scope stack; this is sometimes
        // useful when the env.locStr refers to some template code that
        // was instantiated from somewhere else
        //
        // (unfortunately, env.instantiationLocStack isn't an option b/c
        // it will have been cleared by the automatic invocation of
        // destructors unwinding the stack...)
        cout << env.locationStackString();
      }

      // I changed from using exit(4) here to using abort() because
      // that way the multitest.pl script can distinguish them; the
      // former is reserved for orderly exits, and signals (like
      // SIGABRT) mean that something went really wrong
      abort();
    }
    traceProgress() << "done type checking ("
                    << (getMilliseconds() - tcheckStart)
                    << " ms)\n";

    int numErrors = env.errors.numErrors();
    int numWarnings = env.errors.numWarnings();

    // do this now so that 'printTypedAST' will include CFG info
    #ifdef CFG_EXTENSION
    // A possible TODO is to do this right after each function is type
    // checked.  However, in the current design, that means physically
    // inserting code into Function::tcheck (ifdef'd of course).  A way
    // to do it better would be to have a general post-function-tcheck
    // interface that analyses could hook in to.  That could be augmented
    // by a parsing mode that parsed each function, analyzed it, and then
    // immediately discarded its AST.
    numErrors += computeUnitCFG(unit);
    #endif // CFG_EXTENSION

    // print abstract syntax tree annotated with types
    if (tracingSys("printTypedAST")) {
      unit->debugPrint(cout, 0);
    }

    // structural delta thing
    if (tracingSys("structure")) {
      structurePrint(unit);
    }

    if (tracingSys("secondTcheck")) {
      // this is useful to measure the cost of disambiguation, since
      // now the tree is entirely free of ambiguities
      traceProgress() << "beginning second tcheck...\n";
      Env env2(strTable, lang, tfac, unit);
      unit->tcheck(env2);
      traceProgress() << "end of second tcheck\n";
    }

    // print errors and warnings
    env.errors.print(cout);

    cout << "typechecking results:\n"
         << "  errors:   " << numErrors << "\n"
         << "  warnings: " << numWarnings << "\n";

    if (numErrors != 0) {
      exit(4);
    }

    // verify the tree now has no ambiguities
    if (unit && numAmbiguousNodes(unit) != 0) {
      cout << "UNEXPECTED: ambiguities remain after type checking!\n";
      if (tracingSys("mustBeUnambiguous")) {
        exit(2);
      }
    }

    // check an expected property of the annotated AST
    if (tracingSys("declTypeCheck") || getenv("declTypeCheck")) {
      DeclTypeChecker vis;
      unit->traverse(vis);
      cout << "instances of type != var->type: " << vis.instances << endl;
    }

    // lookup diagnostic
    if (env.collectLookupResults) {
      // scan AST
      NameChecker nc;
      nc.sb << "\"collectLookupResults";
      unit->traverse(nc);
      nc.sb << "\"";

      // compare to given text
      if (0==strcmp(env.collectLookupResults, nc.sb)) {
        // ok
      }
      else {
        cout << "collectLookupResults do not match:\n"
             << "  source: " << env.collectLookupResults << "\n"
             << "  tcheck: " << nc.sb << "\n"
             ;
        exit(4);
      }
    }

//      if (tracingSys("flattenTemplates")) {
//        traceProgress() << "dsw flatten...\n";
//        FlattenEnv env(cout);
//        unit->flatten(env);
//        traceProgress() << "dsw flatten... done\n";
//        cout << endl;
//      }

    if (tracingSys("stopAfterTCheck")) {
      return;
    }
  }

  // semantic elaboration
  if (lang.isCplusplus) {
    long start = getMilliseconds();

    ElabVisitor vis(strTable, tfac, unit);

    // if we are going to pretty print, then we need to retain defunct children
    if (tracingSys("prettyPrint")) {
      vis.cloneDefunctChildren = true;
    }

    unit->traverse(vis);

    traceProgress() << "done elaborating ("
                    << (getMilliseconds() - start)
                    << " ms)\n";

    // print abstract syntax tree annotated with types
    if (tracingSys("printElabAST")) {
      unit->debugPrint(cout, 0);
    }
    if (tracingSys("stopAfterElab")) {
      return;
    }
  }

  // dsw: pretty printing
  if (tracingSys("prettyPrint")) {
    cout << endl;
    traceProgress() << "dsw pretty print...\n";
    PrintEnv env(cout);
    cout << "---- START ----" << endl;
    cout << "// -*-c++-*-" << endl;
    unit->print(env);
    env.finish();
    cout << "---- STOP ----" << endl;
    traceProgress() << "dsw pretty print... done\n";
    cout << endl;
  }

  // test AST cloning
  if (tracingSys("testClone")) {
    TranslationUnit *u2 = unit->clone();

    if (tracingSys("cloneAST")) {
      cout << "------- cloned AST --------\n";
      u2->debugPrint(cout, 0);
    }

    if (tracingSys("cloneCheck")) {
      // dsw: I hope you intend that I should use the cloned TranslationUnit
      Env env3(strTable, lang, tfac, u2);
      u2->tcheck(env3);

      if (tracingSys("cloneTypedAST")) {
        cout << "------- cloned typed AST --------\n";
        u2->debugPrint(cout, 0);
      }

      if (tracingSys("clonePrint")) {
        PrintEnv penv(cout);
        cout << "---- cloned pretty print ----" << endl;
        u2->print(penv);
        penv.finish();
      }
    }
  }

  //traceProgress() << "cleaning up...\n";

  //malloc_stats();

  // delete the tree
  // (currently this doesn't do very much because FakeLists are
  // non-owning, so I won't pretend it does)
  //delete unit;

  strTable.clear();

  //checkHeap();
  //malloc_stats();
}

int main(int argc, char **argv)
{
  try {
    doit(argc, argv);
  }
  catch (xBase &x) {
    cout << x << endl;
    abort();
  }

  //malloc_stats();

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Cubes split<commit_after><|endoftext|>


<commit_before><commit_msg>squash! Added sphere for arcball<commit_after><|endoftext|>


<commit_before>#include "server_functions.h"
#include <string.h>

#include <iostream>
#include <sstream>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <stdlib.h>

#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"

#include "rpc.h"
#include "constants.h"
#include "helper_function.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *> * > proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/
void registration_request_handler(RegisterRequestMessage * message, int sock){
	char * name = message->getName();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature * key = new procedure_signature(name, argTypes);

  server_info * new_msg_loc = new server_info(server_identifier, port, sock);

  int status = 0;

  //if no key dosnt exist in map
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {

    //Adding to the map
    int *memArgTypes = copyArgTypes(argTypes);
    key = procedure_signature(name, memArgTypes);
    proc_loc_dict[key] = new list<server_info *>();
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList

    server_function_info * info = new server_function_info(entry, key);
    roundRobinList.push_back(info);

  }else{

    bool sameLoc = false;
    list<service_info *> *hostList = proc_loc_dict.find[key];

    for (list<service_info *>::iterator it = hostList->begin(); it != hostList->end(); it++) {
      if(it == new_msg_loc){
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something
        sameLoc = true;
      }
    }
    //Same procedure signature, different location
  	if(!sameLoc){
       hostList.push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage * success_message = new RegisterSuccessMessage(status);
  success_message->send(sock);
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
int location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList->begin(); it != roundRobinList->end(); it++){
		//If the name are the same
    if(it->ps->name == message->name && compareArr(it->ps->arrTypes, message->arrTypes)){
		  //When we have identified the correct procedure_signature use round robin and move that service to the end
		  roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      exist = true;
      break;
 		}
	}

  if(exist){
    LocSuccessMessage * success_message = new LocSuccessMessage(it->server_identifier, it->port);
    success_message->send(sock);
  }else{
    LocFailureMessage * failure_message = new LocFailureMessage(0);
    failure_message->send(sock);
  }

	return 0; //LOC_FAILURE
}

int request_handler(Segment * segment, int sock){
  int retval;
  if(segment.getType() == MSG_TYPE_LOC_REQUEST){ //'LOC_REQUEST'
    retval = registration_request_handler(segment->getMessage(), sock);
  }else if (segment.getType() == MSG_TYPE_REGISTER_REQUEST){ //'REGISTER'
    retval = location_request_handler(segment->getMessage(), sock);
  }

	return retval;
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  if (status != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return 0;
  }

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, 5);

  char hostname[256];
  gethostname(hostname, 256);

  struct sockaddr_in sin;
  socklen_t len = sizeof(sin);

  getsockname(sock, (struct sockaddr *)&sin, &len);

  stringstream ss;
  ss << ntohs(sin.sin_port);
  string ps = ss.str();

  cout << "BINDER_ADDRESS " << hostname << endl;
  cout << "BINDER_PORT " << ntohs(sin.sin_port) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = null;
            Segment::receive(sock, segment, status);

            if (status < 0) {
                RegisterFailureMessage * failure_message = new RegisterFailureMessage(status);
                failure_message->send(sock);
                return errorMsg;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return errorMsg;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<commit_msg>update<commit_after>#include "server_functions.h"
#include <string.h>

#include <iostream>
#include <sstream>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <stdlib.h>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"

#include "rpc.h"
#include "constants.h"
#include "helper_function.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *> * > proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/
void registration_request_handler(RegisterRequestMessage * message, int sock){
	char * name = message->getName();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature * key = new procedure_signature(name, argTypes);

  server_info * new_msg_loc = new server_info(server_identifier, port, sock);

  int status = 0;

  //if no key dosnt exist in map
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {

    //Adding to the map
    int *memArgTypes = copyArgTypes(argTypes);
    key = procedure_signature(name, memArgTypes);
    proc_loc_dict[key] = new list<server_info *>();
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList

    server_function_info * info = new server_function_info(entry, key);
    roundRobinList.push_back(info);

  }else{

    bool sameLoc = false;
    list<service_info *> *hostList = proc_loc_dict.find[key];

    for (list<service_info *>::iterator it = hostList->begin(); it != hostList->end(); it++) {
      if(it == new_msg_loc){
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something
        sameLoc = true;
      }
    }
    //Same procedure signature, different location
  	if(!sameLoc){
       hostList.push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage * success_message = new RegisterSuccessMessage(status);
  success_message->send(sock);
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
int location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList->begin(); it != roundRobinList->end(); it++){
		//If the name are the same
    if(it->ps->name == message->name && compareArr(it->ps->arrTypes, message->arrTypes)){
		  //When we have identified the correct procedure_signature use round robin and move that service to the end
		  roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      exist = true;
      break;
 		}
	}

  if(exist){
    LocSuccessMessage * success_message = new LocSuccessMessage(it->server_identifier, it->port);
    success_message->send(sock);
  }else{
    LocFailureMessage * failure_message = new LocFailureMessage(0);
    failure_message->send(sock);
  }

	return 0; //LOC_FAILURE
}

int request_handler(Segment * segment, int sock){
  int retval;
  if(segment.getType() == MSG_TYPE_LOC_REQUEST){ //'LOC_REQUEST'
    retval = registration_request_handler(segment->getMessage(), sock);
  }else if (segment.getType() == MSG_TYPE_REGISTER_REQUEST){ //'REGISTER'
    retval = location_request_handler(segment->getMessage(), sock);
  }

	return retval;
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  if (status != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return 0;
  }

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, 5);

  char hostname[256];
  gethostname(hostname, 256);

  struct sockaddr_in sin;
  socklen_t len = sizeof(sin);

  getsockname(sock, (struct sockaddr *)&sin, &len);

  stringstream ss;
  ss << ntohs(sin.sin_port);
  string ps = ss.str();

  cout << "BINDER_ADDRESS " << hostname << endl;
  cout << "BINDER_PORT " << ntohs(sin.sin_port) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = null;
            Segment::receive(sock, segment, status);

            if (status < 0) {
                RegisterFailureMessage * failure_message = new RegisterFailureMessage(status);
                failure_message->send(sock);
                return errorMsg;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return errorMsg;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<|endoftext|>


<commit_before><commit_msg>add debug to board ai<commit_after><|endoftext|>


<commit_before>//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
#include <string>

namespace clang {
namespace tooling {

namespace {
/// Takes an ast consumer and returns it from CreateASTConsumer. This only
/// works with single translation unit compilations.
class TestAction : public clang::ASTFrontendAction {
 public:
  /// Takes ownership of TestConsumer.
  explicit TestAction(clang::ASTConsumer *TestConsumer)
      : TestConsumer(TestConsumer) {}

 protected:
  virtual clang::ASTConsumer* CreateASTConsumer(
      clang::CompilerInstance& compiler, StringRef dummy) {
    /// TestConsumer will be deleted by the framework calling us.
    return TestConsumer;
  }

 private:
  clang::ASTConsumer * const TestConsumer;
};

class FindTopLevelDeclConsumer : public clang::ASTConsumer {
 public:
  explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
      : FoundTopLevelDecl(FoundTopLevelDecl) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) {
    *FoundTopLevelDecl = true;
    return true;
  }
 private:
  bool * const FoundTopLevelDecl;
};
} // end namespace

TEST(runToolOnCode, FindsTopLevelDeclOnEmptyCode) {
  bool FoundTopLevelDecl = false;
  EXPECT_TRUE(runToolOnCode(
      new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), ""));
  EXPECT_TRUE(FoundTopLevelDecl);
}

namespace {
class FindClassDeclXConsumer : public clang::ASTConsumer {
 public:
  FindClassDeclXConsumer(bool *FoundClassDeclX)
      : FoundClassDeclX(FoundClassDeclX) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) {
    if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
            *GroupRef.begin())) {
      if (Record->getName() == "X") {
        *FoundClassDeclX = true;
      }
    }
    return true;
  }
 private:
  bool *FoundClassDeclX;
};
} // end namespace

TEST(runToolOnCode, FindsClassDecl) {
  bool FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;"));
  EXPECT_TRUE(FoundClassDeclX);

  FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;"));
  EXPECT_FALSE(FoundClassDeclX);
}

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory<SyntaxOnlyAction>());
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

struct IndependentFrontendActionCreator {
  FrontendAction *newFrontendAction() { return new SyntaxOnlyAction; }
};

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
  IndependentFrontendActionCreator Creator;
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory(&Creator));
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

#ifndef LLVM_ON_WIN32
// This test breaks on Windows.

TEST(ToolInvocation, TestMapVirtualFile) {
  clang::FileManager Files((clang::FileSystemOptions()));
  std::vector<std::string> Args;
  Args.push_back("tool-executable");
  Args.push_back("-Idef");
  Args.push_back("-fsyntax-only");
  Args.push_back("test.cpp");
  clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files);
  Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
  Invocation.mapVirtualFile("def/abc", "\n");
  EXPECT_TRUE(Invocation.run());
}

#endif

} // end namespace tooling
} // end namespace clang
<commit_msg>Revert r157819, "#ifdef out a broken test on win32"<commit_after>//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
#include <string>

namespace clang {
namespace tooling {

namespace {
/// Takes an ast consumer and returns it from CreateASTConsumer. This only
/// works with single translation unit compilations.
class TestAction : public clang::ASTFrontendAction {
 public:
  /// Takes ownership of TestConsumer.
  explicit TestAction(clang::ASTConsumer *TestConsumer)
      : TestConsumer(TestConsumer) {}

 protected:
  virtual clang::ASTConsumer* CreateASTConsumer(
      clang::CompilerInstance& compiler, StringRef dummy) {
    /// TestConsumer will be deleted by the framework calling us.
    return TestConsumer;
  }

 private:
  clang::ASTConsumer * const TestConsumer;
};

class FindTopLevelDeclConsumer : public clang::ASTConsumer {
 public:
  explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
      : FoundTopLevelDecl(FoundTopLevelDecl) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) {
    *FoundTopLevelDecl = true;
    return true;
  }
 private:
  bool * const FoundTopLevelDecl;
};
} // end namespace

TEST(runToolOnCode, FindsTopLevelDeclOnEmptyCode) {
  bool FoundTopLevelDecl = false;
  EXPECT_TRUE(runToolOnCode(
      new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), ""));
  EXPECT_TRUE(FoundTopLevelDecl);
}

namespace {
class FindClassDeclXConsumer : public clang::ASTConsumer {
 public:
  FindClassDeclXConsumer(bool *FoundClassDeclX)
      : FoundClassDeclX(FoundClassDeclX) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) {
    if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
            *GroupRef.begin())) {
      if (Record->getName() == "X") {
        *FoundClassDeclX = true;
      }
    }
    return true;
  }
 private:
  bool *FoundClassDeclX;
};
} // end namespace

TEST(runToolOnCode, FindsClassDecl) {
  bool FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;"));
  EXPECT_TRUE(FoundClassDeclX);

  FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;"));
  EXPECT_FALSE(FoundClassDeclX);
}

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory<SyntaxOnlyAction>());
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

struct IndependentFrontendActionCreator {
  FrontendAction *newFrontendAction() { return new SyntaxOnlyAction; }
};

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
  IndependentFrontendActionCreator Creator;
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory(&Creator));
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

TEST(ToolInvocation, TestMapVirtualFile) {
  clang::FileManager Files((clang::FileSystemOptions()));
  std::vector<std::string> Args;
  Args.push_back("tool-executable");
  Args.push_back("-Idef");
  Args.push_back("-fsyntax-only");
  Args.push_back("test.cpp");
  clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files);
  Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
  Invocation.mapVirtualFile("def/abc", "\n");
  EXPECT_TRUE(Invocation.run());
}

} // end namespace tooling
} // end namespace clang
<|endoftext|>