public void Visit(MethodDeclaration methodDeclaration) { methodDeclaration.Qualifiers.Values.Remove(ParadoxStorageQualifier.Override); methodDeclaration.Qualifiers.Values.Remove(ParadoxStorageQualifier.Clone); methodDeclaration.Qualifiers.Values.Remove(ParadoxStorageQualifier.Stage); Visit((Node)methodDeclaration); }
/// <summary> /// Replace the method occurence with its last definition /// </summary> /// <param name="methodDeclaration">the overriding method</param> /// <param name="errorLogger"></param> public void ReplaceVirtualMethod(MethodDeclaration methodDeclaration, LoggerResult errorLogger) { var baseDeclarationMixin = (string)methodDeclaration.GetTag(XenkoTags.BaseDeclarationMixin); foreach (var dict in VirtualTableGroup.Select(x => x.Value)) { for (int i = 0; i < dict.Length; ++i) { var method = dict[i]; var originalDecl = (string)method.GetTag(XenkoTags.BaseDeclarationMixin); // TODO: take typedefs into account... if (originalDecl == baseDeclarationMixin && method.IsSameSignature(methodDeclaration)) { if (method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && !methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Warning(XenkoMessageCode.WarningMissingStageKeyword, methodDeclaration.Span, methodDeclaration, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers |= XenkoStorageQualifier.Stage; } else if (!method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Error(XenkoMessageCode.ErrorExtraStageKeyword, methodDeclaration.Span, methodDeclaration, method, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers.Values.Remove(XenkoStorageQualifier.Stage); } dict[i] = methodDeclaration; } } } }
/// <summary> /// Adds the methods defined in the final mixin /// </summary> /// <param name="methodDeclarations">a list of MethodDeclaration</param> /// <param name="className">the name of the class</param> /// <param name="errorLogger">the logger for errors and warnings</param> public void AddFinalDeclarations(List<MethodDeclaration> methodDeclarations, string className, LoggerResult errorLogger) { var finalDict = new MethodDeclaration[methodDeclarations.Count]; foreach (var methodDecl in methodDeclarations) { var vtableReference = (VTableReference)methodDecl.GetTag(XenkoTags.VirtualTableReference); finalDict[vtableReference.Slot] = methodDecl; // TODO: override/abstract behavior //if (methodDecl.Qualifiers.Contains(XenkoStorageQualifier.Override)) LookForBaseDeclarationMixin(methodDecl, errorLogger); } VirtualTableGroup.Add(className, finalDict); }
/// <summary> /// rename the input/ouput of a method /// </summary> /// <param name="methodDeclaration">the method</param> /// <param name="inputName">the type replacement for Input</param> /// <param name="input2Name">the type replacement for Input2</param> /// <param name="outputName">the type replacement for Output</param> /// <param name="constantsName">the type replacement for Constants</param> private void RenameInputOutput(MethodDeclaration methodDeclaration, TypeName inputName, TypeName input2Name, TypeName outputName, TypeName constantsName) { if (inputName != null) { var replacor = new ParadoxReplaceVisitor(StreamsType.Input, inputName); replacor.Run(methodDeclaration); } if (input2Name != null) { var replacor = new ParadoxReplaceVisitor(StreamsType.Input2, input2Name); replacor.Run(methodDeclaration); } if (outputName != null) { var replacor = new ParadoxReplaceVisitor(StreamsType.Output, outputName); replacor.Run(methodDeclaration); } if (constantsName != null) { var replacor = new ParadoxReplaceVisitor(StreamsType.Constants, constantsName); replacor.Run(methodDeclaration); } }
/// <summary> /// Analyse the method definition and store it in the correct lists (based on storage and stream usage) /// </summary> /// <param name="methodDefinition">the MethodDefinition</param> /// <returns>the input method definition</returns> public override Node Visit(MethodDefinition methodDefinition) { currentVisitedMethod = methodDefinition; if (methodDefinition.Qualifiers.Contains(XenkoStorageQualifier.Abstract)) Error(XenkoMessageCode.ErrorUnnecessaryAbstract, methodDefinition.Span, methodDefinition, analyzedModuleMixin.MixinName); var ret = base.Visit(methodDefinition); PostMethodDeclarationVisit(methodDefinition); return ret; }
/// <summary> /// Initializes a new instance of the <see cref="MethodDefinition"/> class. /// </summary> /// <param name="returntype">The returntype.</param> /// <param name="name">The name.</param> public MethodDefinition(TypeBase returntype, string name) : this() { ReturnType = returntype; Name = new Identifier(name); declaration = this; }
/// <summary> /// Initializes a new instance of the <see cref="MethodDefinition"/> class. /// </summary> public MethodDefinition() { Body = new StatementList(); declaration = this; }
/// <summary> /// Store the method in the correct list /// </summary> /// <param name="methodDeclaration"></param> private void StoreMethod(MethodDeclaration methodDeclaration) { if (!parsingInfo.ClassReferences.MethodsReferences.ContainsKey(methodDeclaration)) parsingInfo.ClassReferences.MethodsReferences.Add(methodDeclaration, new HashSet<MethodInvocationExpression>()); }
/// <summary> /// Copies declartion to another instance. /// </summary> /// <param name="target">The target instance.</param> public void CopyTo(MethodDeclaration target) { target.Attributes = Attributes; target.Name = Name; target.Parameters = Parameters; target.Qualifiers = Qualifiers; target.ReturnType = ReturnType; }
public virtual void Visit(MethodDeclaration methodDeclaration) { WriteLinkLine(methodDeclaration); WriteMethodDeclaration(methodDeclaration).WriteLine(";"); }
/// <summary> /// Get all the calls from the current method /// </summary> /// <param name="currentMethod">the current method</param> /// <param name="calledMethods">list of method called</param> /// <returns>true if calls were found</returns> //private bool TryGetMethodCalls(MethodDeclaration currentMethod, out List<MethodInvocationExpression> calledMethods) private bool TryGetMethodCalls(MethodDeclaration currentMethod, out List<MethodDeclaration> calledMethods) { List<StreamUsageInfo> streamUsageInfos; if (streamsUsages.TryGetValue(currentMethod, out streamUsageInfos)) { //calledMethods = streamUsageInfos.Where(x => x.CallType == StreamCallType.Method).Select(x => x.MethodReference).ToList(); calledMethods = streamUsageInfos.Where(x => x.CallType == StreamCallType.Method).Select(x => x.MethodDeclaration).ToList(); return true; } calledMethods = null; return false; }
protected void Visit(MethodDeclaration methodDeclaration) { currentVisitedMethod = methodDeclaration; if (!methodDeclaration.Qualifiers.Contains(ParadoxStorageQualifier.Abstract)) Error(ParadoxMessageCode.ErrorMissingAbstract, methodDeclaration.Span, methodDeclaration, analyzedModuleMixin.MixinName); if (methodDeclaration.Qualifiers.Contains(ParadoxStorageQualifier.Override)) Error(ParadoxMessageCode.ErrorUnnecessaryOverride, methodDeclaration.Span, methodDeclaration, analyzedModuleMixin.MixinName); Visit((Node)methodDeclaration); PostMethodDeclarationVisit(methodDeclaration); }
/// <summary> /// Recursively rename the input/output types /// </summary> /// <param name="methodDeclaration">the method to explore</param> /// <param name="inputName">the TypeName for Input</param> /// <param name="input2Name">the TypeName for Input2</param> /// <param name="outputName">the TypeName for Output</param> /// <param name="constantsName">the TypeName for Constants</param> /// <param name="visitedMethods">the already visited methods</param> private void RecursiveRename(MethodDeclaration methodDeclaration, TypeName inputName, TypeName input2Name, TypeName outputName, TypeName constantsName, Stack<MethodDeclaration> visitedMethods) { if (methodDeclaration == null || visitedMethods.Contains(methodDeclaration)) return; RenameInputOutput(methodDeclaration, inputName, input2Name, outputName, constantsName); visitedMethods.Push(methodDeclaration); List<MethodDeclaration> calls; if (TryGetMethodCalls(methodDeclaration, out calls)) { foreach (var calledmethod in calls) RecursiveRename(calledmethod, inputName, input2Name, outputName, constantsName, visitedMethods); } }
/// <summary> /// Finds the usage of the streams /// </summary> /// <param name="currentMethod">the current method</param> /// <param name="inStreamList">list of in-streams</param> /// <param name="outStreamList">list of out-streams</param> /// <param name="visitedMethods">list of already visited methods</param> private void FindStreamsUsage(MethodDeclaration currentMethod, List<IDeclaration> inStreamList, List<IDeclaration> outStreamList, List<MethodDeclaration> visitedMethods) { if (visitedMethods.Contains(currentMethod)) { errorWarningLog.Error(ParadoxMessageCode.ErrorRecursiveCall, currentMethod.Span, currentMethod); return; } if (currentMethod != null) { var newListVisitedMethods = new List<MethodDeclaration>(); newListVisitedMethods.AddRange(visitedMethods); newListVisitedMethods.Add(currentMethod); List<StreamUsageInfo> streamUsageList; if (streamsUsages.TryGetValue(currentMethod, out streamUsageList)) { // look for stream usage inside the function foreach (var streamUsage in streamUsageList) { if (streamUsage.CallType == StreamCallType.Member) { var isOutStream = outStreamList.Contains(streamUsage.Variable); var isInStream = inStreamList.Contains(streamUsage.Variable); if (streamUsage.Usage.IsWrite() && !isOutStream) { outStreamList.Add(streamUsage.Variable); if (streamUsage.Usage.IsPartial() && !isInStream) // force variable to be passed from previous stages when affectation is only partial. inStreamList.Add(streamUsage.Variable); } else if (streamUsage.Usage.IsRead() && !isOutStream && !isInStream) // first read inStreamList.Add(streamUsage.Variable); } else if (streamUsage.CallType == StreamCallType.Method) { if (streamUsage.MethodDeclaration != null) // way to check the built-in functions (could be improved?) FindStreamsUsage(streamUsage.MethodDeclaration, inStreamList, outStreamList, newListVisitedMethods); } else if (streamUsage.CallType != StreamCallType.Direct) // should not happen errorWarningLog.Error(ParadoxMessageCode.ErrorStreamUsageInitialization, streamUsage.Expression.Span, streamUsage.Expression); } } } }
/// <summary> /// Get the streams usage for this entrypoint /// </summary> /// <param name="moduleMixin">the current module mixin</param> /// <param name="entryPoint">the entrypoint method</param> /// <returns>a StreamStageUsage containing the streams usages</returns> private StreamStageUsage StreamAnalysisPerShader(ModuleMixin moduleMixin, MethodDeclaration entryPoint, PdxShaderStage shaderStage) { var visitedMethods = new List<MethodDeclaration>(); var streamStageUsage = new StreamStageUsage { ShaderStage = shaderStage }; FindStreamsUsage(entryPoint, streamStageUsage.InStreamList, streamStageUsage.OutStreamList, visitedMethods); visitedMethods.Clear(); return streamStageUsage; }
/// <summary> /// Insert a method reference /// </summary> /// <param name="methodDeclaration">the method</param> /// <param name="expression">the reference</param> public void InsertMethod(MethodDeclaration methodDeclaration, MethodInvocationExpression expression) { if (!MethodsReferences.ContainsKey(methodDeclaration)) MethodsReferences.Add(methodDeclaration, new HashSet<MethodInvocationExpression>()); MethodsReferences[methodDeclaration].Add(expression); }
/// <summary> /// Get the overloaded method from one of its base declaration /// </summary> /// <param name="methodDeclaration">the MethodDeclaration</param> /// <returns>the overloaded MethodDeclaration</returns> public MethodDeclaration GetMethodFromDeclaration(MethodDeclaration methodDeclaration) { var info = (VTableReference)methodDeclaration.GetTag(ParadoxTags.VirtualTableReference); return VirtualTable.GetMethod(info.Shader, info.Slot); }
/// <summary> /// Test if a method declaration has the same signature. /// </summary> /// <param name="methodDeclaration">The method declaration.</param> /// <returns>True if the method passed has the same signature</returns> public bool IsSameSignature(MethodDeclaration methodDeclaration) { if (methodDeclaration == null) return false; if (Name != methodDeclaration.Name) return false; if (Parameters.Count != methodDeclaration.Parameters.Count) return false; for (int i = 0; i < Parameters.Count; i++) { var parameter = Parameters[i]; var parameterAgainst = methodDeclaration.Parameters[i]; var parameterType = parameter.Type.ResolveType(); var parameterAgainstType = parameterAgainst.Type.ResolveType(); if (parameterType != parameterAgainstType) { return false; } } return true; }
protected static void InitializeBuiltins() { foreach (var function in Function.Functions) { foreach (var p in EnumerateParameters(function.Parameters[0])) { var returnType = function.Return(function, new[] { p }); var parameterTypes = function.ParamList(function, new[] { p }); var methodDeclaration = new MethodDeclaration(); methodDeclaration.IsBuiltin = true; methodDeclaration.Name = new Identifier(function.Name); methodDeclaration.ReturnType = returnType; foreach (var parameterType in parameterTypes) methodDeclaration.Parameters.Add( new Ast.Parameter { DeclaringMethod = methodDeclaration, Type = parameterType } ); defaultDeclarations.Add(methodDeclaration); } } defaultDeclarations.AddRange(declaredMethods); foreach (var methodDeclaration in declaredMethods) { var newMethodDeclaration = new MethodDeclaration(); newMethodDeclaration.IsBuiltin = true; newMethodDeclaration.Name = new Identifier(methodDeclaration.Name); newMethodDeclaration.ReturnType = methodDeclaration.ReturnType; foreach (var parameter in methodDeclaration.Parameters) { var parameterType = parameter.Type; if (parameterType is SamplerType) { parameterType = SamplerType.Sampler; } newMethodDeclaration.Parameters.Add(new Ast.Parameter { DeclaringMethod = newMethodDeclaration, Type = parameterType }); } defaultDeclarations.Add(newMethodDeclaration); } // adding remaining functions that doesn't have multiple versions defaultDeclarations.Add(GenericMethod("AllMemoryBarrier", TypeBase.Void)); defaultDeclarations.Add(GenericMethod("AllMemoryBarrierWithGroupSync", TypeBase.Void)); defaultDeclarations.Add(GenericMethod("D3DCOLORtoUBYTE4", VectorType.Int4, GenericParam("x", VectorType.Float4))); defaultDeclarations.Add(GenericMethod("DeviceMemoryBarrier", TypeBase.Void)); defaultDeclarations.Add(GenericMethod("DeviceMemoryBarrierWithGroupSync", TypeBase.Void)); defaultDeclarations.Add(GenericMethod("GetRenderTargetSampleCount", ScalarType.UInt)); defaultDeclarations.Add(GenericMethod("GetRenderTargetSamplePosition", ScalarType.UInt, GenericParam("x", ScalarType.Int))); defaultDeclarations.Add(GenericMethod("GroupMemoryBarrier", TypeBase.Void)); }
/// <inheritdoc /> public override void Visit(MethodDeclaration methodDeclaration) { WriteLinkLine(methodDeclaration); WriteMethodDeclaration(methodDeclaration).WriteLine(";"); }
private static MethodDeclaration GenericMethod(string methodName, TypeBase returnType, List<GenericParameterConstraint> constraints, params Ast.Parameter[] parameters) { var methodDeclaration = new MethodDeclaration() { Name = new Identifier(methodName), ReturnType = returnType }; methodDeclaration.IsBuiltin = true; if (constraints != null) methodDeclaration.ParameterConstraints = constraints; methodDeclaration.Parameters.AddRange(parameters); return methodDeclaration; }
/// <summary> /// Writes the specified method declaration. /// </summary> /// <param name="methodDeclaration"> /// The method declaration. /// </param> /// <returns> /// This instance /// </returns> protected virtual ShaderWriter WriteMethodDeclaration(MethodDeclaration methodDeclaration) { isVisitingVariableInlines = true; // Pre Attributes Write(methodDeclaration.Attributes, true); // Pre Qualifiers Write(methodDeclaration.Qualifiers, true); VisitDynamic(methodDeclaration.ReturnType); Write(" "); Write(methodDeclaration.Name); Write("("); for (int i = 0; i < methodDeclaration.Parameters.Count; i++) { var parameter = methodDeclaration.Parameters[i]; if (i > 0) Write(",").WriteSpace(); VisitDynamic(parameter); } Write(")"); // Post Qualifiers Write(methodDeclaration.Qualifiers, false); // Post Attributes Write(methodDeclaration.Attributes, false); isVisitingVariableInlines = false; return this; }
public MethodDeclarationShaderCouple(MethodDeclaration method, ShaderClassType shader) { Method = method; Shader = shader; }
/// <summary> /// Finds the location of the method in the virtual table of its definition mixin /// </summary> /// <param name="methodDeclaration"></param> /// <returns></returns> public VTableReference GetBaseDeclaration(MethodDeclaration methodDeclaration) { var baseMethodDeclMixin = methodDeclaration.GetTag(XenkoTags.BaseDeclarationMixin) as string; var slot = -1; var vt = VirtualTableGroup[baseMethodDeclMixin]; for (int i = 0; i < vt.Length; ++i) { if (methodDeclaration.IsSameSignature(vt[i])) { slot = i; break; } } return new VTableReference { Shader = baseMethodDeclMixin, Slot = slot }; }
/// <summary> /// Checks that the method does not have mixin as parameter or return type /// </summary> /// <param name="methodDeclaration">the method.</param> private void CheckParamatersAndReturnType(MethodDeclaration methodDeclaration) { foreach (var parameter in methodDeclaration.Parameters) { if (parameter.Type.TypeInference.Declaration is ShaderClassType) Error(XenkoMessageCode.ErrorShaderClassTypeParameter, methodDeclaration.Span, methodDeclaration, parameter, analyzedModuleMixin.MixinName); } if (methodDeclaration.ReturnType.TypeInference.Declaration is ShaderClassType) Error(XenkoMessageCode.ErrorShaderClassReturnType, methodDeclaration.Span, methodDeclaration, analyzedModuleMixin.MixinName); }
/// <summary> /// Find the base definition of the method and override its occurence /// </summary> /// <param name="methodDeclaration"></param> /// <param name="errorLogger"></param> private void LookForBaseDeclarationMixin(MethodDeclaration methodDeclaration, LoggerResult errorLogger) { foreach (var dict in VirtualTableGroup.Select(x => x.Value)) { for (int i = 0; i < dict.Length; ++i) { var method = dict[i]; var baseDeclarationMixin = (string)method.GetTag(XenkoTags.BaseDeclarationMixin); // TODO: take typedefs into account... if (method.IsSameSignature(methodDeclaration)) { var sourceShader = ((ModuleMixin)methodDeclaration.GetTag(XenkoTags.ShaderScope)).MixinName; // test override if (methodDeclaration is MethodDefinition && method is MethodDefinition && !methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Override)) errorLogger.Error(XenkoMessageCode.ErrorMissingOverride, method.Span, methodDeclaration, sourceShader); if (!(methodDeclaration is MethodDefinition)) errorLogger.Error(XenkoMessageCode.ErrorOverrindingDeclaration, method.Span, methodDeclaration, sourceShader); if (method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && !methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Warning(XenkoMessageCode.WarningMissingStageKeyword, methodDeclaration.Span, methodDeclaration, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers |= XenkoStorageQualifier.Stage; } else if (!method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Error(XenkoMessageCode.ErrorExtraStageKeyword, methodDeclaration.Span, methodDeclaration, method, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers.Values.Remove(XenkoStorageQualifier.Stage); } dict[i] = methodDeclaration; methodDeclaration.SetTag(XenkoTags.BaseDeclarationMixin, baseDeclarationMixin); } } } }
/// <summary> /// Performs operations applicable for MethodDefinition & MethodDeclaration nodes /// </summary> /// <param name="methodDeclaration">the method declaration or definition</param> private void PostMethodDeclarationVisit(MethodDeclaration methodDeclaration) { currentVisitedMethod = null; StoreMethod(methodDeclaration); CheckParamatersAndReturnType(methodDeclaration); }