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); }
void AddPrimitiveIntrinsics(FrontEndTranslator translator) { var floatType = translator.FindType(typeof(float)); SpecialResolvers.CreateSimpleIntrinsicFunction(translator, new FunctionKey("float.operator +(float, float)"), OpInstructionType.OpFAdd, floatType); }