<commit_before>/*
 * HLSLAnalyzer.cpp
 * 
 * This file is part of the XShaderCompiler project (Copyright (c) 2014-2016 by <NAME>)
 * See "LICENSE.txt" for license information.
 */

#include "HLSLAnalyzer.h"
#include "HLSLIntrinsics.h"
#include "HLSLKeywords.h"
#include "ConstExprEvaluator.h"
#include "EndOfScopeAnalyzer.h"
#include "Exception.h"
#include "Helper.h"


namespace Xsc
{


static ShaderVersion GetShaderModel(const InputShaderVersion v)
{
    switch (v)
    {
        case InputShaderVersion::HLSL3: return { 3, 0 };
        case InputShaderVersion::HLSL4: return { 4, 0 };
        case InputShaderVersion::HLSL5: return { 5, 0 };
    }
    return { 1, 0 };
}

HLSLAnalyzer::HLSLAnalyzer(Log* log) :
    Analyzer{ log }
{
}

void HLSLAnalyzer::DecorateASTPrimary(
    Program& program, const ShaderInput& inputDesc, const ShaderOutput& outputDesc)
{
    /* Store parameters */
    entryPoint_             = inputDesc.entryPoint;
    secondaryEntryPoint_    = inputDesc.secondaryEntryPoint;
    shaderTarget_           = inputDesc.shaderTarget;
    versionIn_              = inputDesc.shaderVersion;
    shaderModel_            = GetShaderModel(inputDesc.shaderVersion);
    preferWrappers_         = outputDesc.options.preferWrappers;

    /* Decorate program AST */
    program_ = &program;

    Visit(&program);

    /* Check if secondary entry point has been found */
    if (!secondaryEntryPoint_.empty() && !secondaryEntryPointFound_)
        Warning("secondary entry point \"" + secondaryEntryPoint_ + "\" not found");
}


/*
 * ======= Private: =======
 */

void HLSLAnalyzer::ErrorIfAttributeNotFound(bool found, const std::string& attribDesc)
{
    if (!found)
        Error("missing '" + attribDesc + "' attribute for entry point", nullptr, HLSLErr::ERR_ATTRIBUTE);
}

/* ------- Visit functions ------- */

#define IMPLEMENT_VISIT_PROC(AST_NAME) \
    void HLSLAnalyzer::Visit##AST_NAME(AST_NAME* ast, void* args)

IMPLEMENT_VISIT_PROC(Program)
{
    /* Analyze context of the entire program */
    Visit(ast->globalStmnts);

    /* Check if fragment shader uses a slightly different screen space (VPOS vs. SV_Position) */
    if (shaderTarget_ == ShaderTarget::FragmentShader && versionIn_ <= InputShaderVersion::HLSL3)
        program_->layoutFragment.pixelCenterInteger = true;
}

IMPLEMENT_VISIT_PROC(CodeBlock)
{
    OpenScope();
    {
        Visit(ast->stmnts);
    }
    CloseScope();
}

IMPLEMENT_VISIT_PROC(FunctionCall)
{
    PushFunctionCall(ast);
    {
        /* Analyze function arguments first */
        Visit(ast->arguments);

        /* Then analyze function name */
        if (ast->varIdent)
        {
            if (ast->varIdent->next)
            {
                /* Check if the function call refers to an intrinsic */
                auto intrIt = HLSLIntrinsics().find(ast->varIdent->next->ident);
                if (intrIt != HLSLIntrinsics().end())
                {
                    auto intrinsic = intrIt->second.intrinsic;

                    /* Analyze variable identifier (symbolRef is needed next) */
                    AnalyzeVarIdent(ast->varIdent.get());

                    /* Verify intrinsic for respective object class */
                    switch (ast->varIdent->symbolRef->Type())
                    {
                        case AST::Types::BufferDecl:
                            if (!IsTextureIntrinsic(intrinsic))
                                Error("invalid intrinsic '" + ast->varIdent->next->ident + "' for a texture object", ast);
                            break;

                        default:
                            break;
                    }

                    AnalyzeFunctionCallIntrinsic(ast, intrIt->second);
                }
                else
                    AnalyzeFunctionCallStandard(ast);
            }
            else
            {
                /* Check if the function call refers to an intrinsic */
                auto intrIt = HLSLIntrinsics().find(ast->varIdent->ident);
                if (intrIt != HLSLIntrinsics().end())
                    AnalyzeFunctionCallIntrinsic(ast, intrIt->second);
                else
                    AnalyzeFunctionCallStandard(ast);
            }
        }
    }
    PopFunctionCall();
}

IMPLEMENT_VISIT_PROC(ArrayDimension)
{
    if (ast->expr && ast->expr->Type() != AST::Types::NullExpr)
    {
        Visit(ast->expr);

        /* Evalutate constant expression and store as array dimension size */
        auto value = EvaluateConstExprInt(*ast->expr);

        ast->size = value;
    }<commit_msg>Extended HLSLAnalyzer for class member intrinsics.<commit_after>/*
 * HLSLAnalyzer.cpp
 * 
 * This file is part of the XShaderCompiler project (Copyright (c) 2014-2016 by <NAME>)
 * See "LICENSE.txt" for license information.
 */

#include "HLSLAnalyzer.h"
#include "HLSLIntrinsics.h"
#include "HLSLKeywords.h"
#include "ConstExprEvaluator.h"
#include "EndOfScopeAnalyzer.h"
#include "Exception.h"
#include "Helper.h"


namespace Xsc
{


static ShaderVersion GetShaderModel(const InputShaderVersion v)
{
    switch (v)
    {
        case InputShaderVersion::HLSL3: return { 3, 0 };
        case InputShaderVersion::HLSL4: return { 4, 0 };
        case InputShaderVersion::HLSL5: return { 5, 0 };
    }
    return { 1, 0 };
}

HLSLAnalyzer::HLSLAnalyzer(Log* log) :
    Analyzer{ log }
{
}

void HLSLAnalyzer::DecorateASTPrimary(
    Program& program, const ShaderInput& inputDesc, const ShaderOutput& outputDesc)
{
    /* Store parameters */
    entryPoint_             = inputDesc.entryPoint;
    secondaryEntryPoint_    = inputDesc.secondaryEntryPoint;
    shaderTarget_           = inputDesc.shaderTarget;
    versionIn_              = inputDesc.shaderVersion;
    shaderModel_            = GetShaderModel(inputDesc.shaderVersion);
    preferWrappers_         = outputDesc.options.preferWrappers;

    /* Decorate program AST */
    program_ = &program;

    Visit(&program);

    /* Check if secondary entry point has been found */
    if (!secondaryEntryPoint_.empty() && !secondaryEntryPointFound_)
        Warning("secondary entry point \"" + secondaryEntryPoint_ + "\" not found");
}


/*
 * ======= Private: =======
 */

void HLSLAnalyzer::ErrorIfAttributeNotFound(bool found, const std::string& attribDesc)
{
    if (!found)
        Error("missing '" + attribDesc + "' attribute for entry point", nullptr, HLSLErr::ERR_ATTRIBUTE);
}

/* ------- Visit functions ------- */

#define IMPLEMENT_VISIT_PROC(AST_NAME) \
    void HLSLAnalyzer::Visit##AST_NAME(AST_NAME* ast, void* args)

IMPLEMENT_VISIT_PROC(Program)
{
    /* Analyze context of the entire program */
    Visit(ast->globalStmnts);

    /* Check if fragment shader uses a slightly different screen space (VPOS vs. SV_Position) */
    if (shaderTarget_ == ShaderTarget::FragmentShader && versionIn_ <= InputShaderVersion::HLSL3)
        program_->layoutFragment.pixelCenterInteger = true;
}

IMPLEMENT_VISIT_PROC(CodeBlock)
{
    OpenScope();
    {
        Visit(ast->stmnts);
    }
    CloseScope();
}

IMPLEMENT_VISIT_PROC(FunctionCall)
{
    PushFunctionCall(ast);
    {
        /* Analyze function arguments first */
        Visit(ast->arguments);

        /* Then analyze function name */
        if (ast->varIdent)
        {
            if (ast->varIdent->next)
            {
                /* Check if the function call refers to an intrinsic */
                auto intrIt = HLSLIntrinsics().find(ast->varIdent->next->ident);
                if (intrIt != HLSLIntrinsics().end())
                {
                    auto intrinsic = intrIt->second.intrinsic;

                    /* Analyze variable identifier (symbolRef is needed next) */
                    AnalyzeVarIdent(ast->varIdent.get());

                    /* Verify intrinsic for respective object class */
                    if (auto symbolRef = ast->varIdent->symbolRef)
                    {
                        switch (symbolRef->Type())
                        {
                            case AST::Types::BufferDecl:
                                if (!IsTextureIntrinsic(intrinsic))
                                    Error("invalid intrinsic '" + ast->varIdent->next->ident + "' for a buffer object", ast);
                                break;

                            default:
                                break;
                        }
                    }
                    else
                        Error("intrinsic '" + ast->varIdent->next->ident + "' not declared in object '" + ast->varIdent->ident + "'", ast);

                    AnalyzeFunctionCallIntrinsic(ast, intrIt->second);
                }
                else
                    AnalyzeFunctionCallStandard(ast);
            }
            else
            {
                /* Does the function call refer to an intrinsic? */
                auto intrIt = HLSLIntrinsics().find(ast->varIdent->ident);
                if (intrIt != HLSLIntrinsics().end())
                {
                    /* Is this a global intrinsic? */
                    if (IsGlobalIntrinsic(intrIt->second.intrinsic))
                        AnalyzeFunctionCallIntrinsic(ast, intrIt->second);
                    else
                        AnalyzeFunctionCallStandard(ast);
                }
                else
                    AnalyzeFunctionCallStandard(ast);
            }
        }
    }
    PopFunctionCall();
}

IMPLEMENT_VISIT_PROC(ArrayDimension)
{
    if (ast->expr && ast->expr->Type() != AST::Types::NullExpr)
    {
        Visit(ast->expr);

        /* Evalutate constant expression and store as array dimension size */
        auto value = EvaluateConstExprInt(*ast->expr);

        ast->size = value;
    }
{'fraction_non_alphanumeric': 0.11244732243807175, 'fraction_numerical': 0.004111419467571179, 'mean_word_length': 1.973716381418093, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6071299', 'n_tokens_mistral': 2781, 'n_tokens_neox': 2593, 'n_words': 584}