public void VisitMethod(CSharpSyntaxNode node, ShaderFunction shaderFunction)
        {
            var fnSymbol = mFrontEnd.mSemanticModel.GetDeclaredSymbol(node) as IMethodSymbol;

            // Handle intrinsics. If we have a resolver for a special handler then call that and return.
            if (SpecialResolvers.TryProcessIntrinsicMethod(mFrontEnd, fnSymbol))
            {
                return;
            }

            // Add the current function as the active one and the parameter
            mContext.mCurrentFunction = shaderFunction;

            // Start writing out the parameters (so the parameter block is the active one)
            mContext.mCurrentBlock = shaderFunction.mParametersBlock;
            // Add the 'this' op if it exists
            if (!fnSymbol.IsStatic)
            {
                var selfType = mContext.mCurrentType;
                var thisType = selfType.FindPointerType(StorageClass.Function);
                var selfOp   = CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionParameter, thisType, null);
                selfOp.DebugInfo.Name = "self";
                mContext.mThisOp      = selfOp;
            }
            // Add the function parameter ops
            foreach (var parameter in fnSymbol.Parameters)
            {
                var parameterType = FindParameterType(mFrontEnd.mCurrentLibrary.FindType(new TypeKey(parameter.Type)), parameter);
                var paramOp       = CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionParameter, parameterType, null);

                // Extract the debug info. We can't get this from the node because the node isn't always a method with arguments.
                // // If this is a get/set then the arguments are implicit and there's no location to look at.
                if (parameter.Locations != null && parameter.Locations.Length != 0)
                {
                    paramOp.DebugInfo.Location = parameter.Locations[0];
                }
                paramOp.DebugInfo.Name = parameter.Name;

                // Also map parameter symbols in this scope to their ops so we can look them up later when visiting identifiers
                mContext.mSymbolToIRMap.Add(parameter, paramOp);
            }

            // Now set the body as the current scope and visit the function
            var firstBlock = new ShaderBlock();

            shaderFunction.mBlocks.Add(firstBlock);
            mContext.mCurrentBlock = firstBlock;
            mCommonPass.Visit(node);
            // SpirV has some special rules about returns. Make sure to address these by fixing up missing terminators or removing extra functions.
            mFrontEnd.FixupBlockTerminators(shaderFunction);

            // Clear the function out of the current context
            mContext.mThisOp          = null;
            mContext.mCurrentBlock    = null;
            mContext.mCurrentFunction = null;
        }
        public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
        {
            var fnSymbol = mFrontEnd.mSemanticModel.GetDeclaredSymbol(node) as IMethodSymbol;

            // Handle intrinsics. If we have a resolver for a special handler then call that and return.
            if (SpecialResolvers.TryProcessIntrinsicMethod(mFrontEnd, fnSymbol))
            {
                return;
            }

            var functionName      = "Constructor";
            var returnType        = FindType(typeof(void));
            var shaderConstructor = CreateFunction(node, functionName, returnType);

            shaderConstructor.DebugInfo.Name = mFrontEnd.GenerateDebugFunctionName(mContext.mCurrentType, functionName);
        }
        public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
        {
            var fnSymbol = mFrontEnd.mSemanticModel.GetDeclaredSymbol(node) as IMethodSymbol;

            // Visit any remaining methods (not intrinsics) on the primitive type. This is necessary for any helper functions to work
            var attributes = mFrontEnd.ParseAttributes(GetDeclaredSymbol(node));

            // Handle intrinsics. If we have a resolver for a special handler then call that and return.
            if (SpecialResolvers.TryProcessIntrinsicMethod(mFrontEnd, fnSymbol))
            {
                return;
            }

            if (IsIntrinsic(attributes))
            {
                return;
            }

            var returnType = FindType(node.ReturnType);

            CreateFunction(node, node.Identifier.Text, returnType);
        }