protected override void Analyze(IInvocationExpression expression, IDaemonProcess daemonProcess, DaemonProcessKind kind, IHighlightingConsumer consumer) { if (PerformanceCriticalCodeStageUtil.IsInvocationExpensive(expression)) { CreateHiglighting(expression, consumer); } else if (kind == DaemonProcessKind.GLOBAL_WARNINGS) { var declaredElement = CallGraphUtil.GetCallee(expression); if (declaredElement == null) { return; } var id = myProvider.GetElementId(declaredElement); if (!id.HasValue) { return; } if (mySwaExtensionProvider.IsMarkedByCallGraphRootMarksProvider(myExpensiveCodeCallGraphAnalyzer.Id, true, id.Value)) { CreateHiglighting(expression, consumer); } } }
protected override void Analyze(IInvocationExpression expression, IHighlightingConsumer consumer, IReadOnlyCallGraphContext context) { var callee = CallGraphUtil.GetCallee(expression); if (PerformanceCriticalCodeStageUtil.IsInvokedElementExpensive(callee as IMethod) || myContextProvider.IsMarkedStage(callee, context)) { CreateHighlighting(expression, consumer); } }
protected override void Analyze(IInvocationExpression expression, IDaemonProcess daemonProcess, DaemonProcessKind kind, IHighlightingConsumer consumer) { var callee = CallGraphUtil.GetCallee(expression); if (myContextProvider.IsMarked(callee, kind)) { CreateHighlighting(expression, consumer); } }
public static IDeclaredElement ExtractDeclaredElementForProvider([CanBeNull] ITreeNode node) { switch (node) { case IDeclaration declaration: return(declaration.DeclaredElement); case ICSharpExpression expression: return(CallGraphUtil.GetCallee(expression)); } return(null); }
public static bool IsBurstContextBannedNode(ITreeNode node) { switch (node) { case IThrowStatement _: case IThrowExpression _: case IInvocationExpression invocationExpression when CallGraphUtil.GetCallee(invocationExpression) is IMethod method && IsBurstDiscarded(method): case IFunctionDeclaration functionDeclaration when IsBurstContextBannedForFunction(functionDeclaration.DeclaredElement): return(true); default: return(false); } }
public static bool CheckAndAnalyze(ITreeNode node, IHighlighting highlighting, IHighlightingConsumer consumer) { var firstNode = node; do { var parent = node.Parent; if (parent is IExpressionInitializer expressionInitializer) { if (ReferenceEquals(expressionInitializer.Value, firstNode)) { do { node = parent; parent = node.Parent; } while (parent != null && !(parent is IInitializerOwnerDeclaration)); if (parent == null) { return(true); } var initializerOwnerDeclaration = (IInitializerOwnerDeclaration)parent; if (ReferenceEquals(initializerOwnerDeclaration.Initializer, expressionInitializer)) { var typeOwner = initializerOwnerDeclaration.DeclaredElement as ITypeOwner; var type = typeOwner?.Type; if (BurstCodeAnalysisUtil.IsFixedString(type)) { return(false); } } } consumer?.AddHighlighting(highlighting); return(true); } if (parent is ICSharpArgument cSharpArgument) { var invocationInfo = cSharpArgument.Invocation; if (invocationInfo is IInvocationExpression info) { var callee = CallGraphUtil.GetCallee(info) as IMethod; if (BurstCodeAnalysisUtil.IsBurstPermittedString(cSharpArgument.GetExpressionType().ToIType()) && callee != null && (BurstCodeAnalysisUtil.IsDebugLog(callee) || BurstCodeAnalysisUtil.IsStringFormat(callee))) { return(false); } } consumer?.AddHighlighting(highlighting); return(true); } if (parent is IAssignmentExpression assignmentExpression) { if (assignmentExpression.Dest == node) { return(false); } if (BurstCodeAnalysisUtil.IsFixedString(assignmentExpression.Dest.Type()) && assignmentExpression.Source.Type().IsString()) { return(false); } consumer?.AddHighlighting(highlighting); return(true); } if (parent is ITypeMemberDeclaration) { consumer?.AddHighlighting(highlighting); return(true); } node = parent; } while (node != null); consumer?.AddHighlighting(highlighting); return(true); }
public override LocalList <IDeclaredElement> GetRootMarksFromNode(ITreeNode currentNode, IDeclaredElement containingFunction) { var result = new HashSet <IDeclaredElement>(); switch (currentNode) { case IStructDeclaration structDeclaration when structDeclaration.DeclaredElement is IStruct @struct && @struct.HasAttributeInstance(KnownTypes.BurstCompileAttribute, AttributesSource.Self): { var superTypes = @struct.GetAllSuperTypes(); var interfaces = superTypes .Where(declaredType => declaredType.IsInterfaceType()) .Select(declaredType => declaredType.GetTypeElement()) .WhereNotNull() .Where(typeElement => typeElement.HasAttributeInstance(KnownTypes.JobProducerAttrubyte, AttributesSource.Self)) .ToList(); var structMethods = @struct.Methods.ToList(); foreach (var @interface in interfaces) { var interfaceMethods = @interface.Methods.ToList(); var overridenMethods = structMethods .Where(m => interfaceMethods.Any(m.OverridesOrImplements)) .ToList(); foreach (var overridenMethod in overridenMethods) { result.Add(overridenMethod); } } break; } case IInvocationExpression invocationExpression: { if (!(CallGraphUtil.GetCallee(invocationExpression) is IMethod method)) { break; } var containingType = method.GetContainingType(); if (containingType == null) { break; } if (method.Parameters.Count == 1 && method.TypeParameters.Count == 1 && method.ShortName == "CompileFunctionPointer" && containingType.GetClrName().Equals(KnownTypes.BurstCompiler)) { var argumentList = invocationExpression.ArgumentList.Arguments; if (argumentList.Count != 1) { break; } var argument = argumentList[0].Value; if (argument == null) { break; } var possibleDeclaredElements = CallGraphUtil.ExtractCallGraphDeclaredElements(argument); foreach (var declaredElement in possibleDeclaredElements) { if (declaredElement != null) { result.Add(declaredElement); } } } break; } } return(new LocalList <IDeclaredElement>(result.WhereNotNull())); }
protected override bool CheckAndAnalyze(IInvocationExpression invocationExpression, IHighlightingConsumer consumer) { //algorithm: //if conditional qualifier is open type // return // REASON: burst allows to instantiate generics only with structures. if it is instantiated with class - // it would be highlighted where generics called. if it is instantiated with structure - 2 possible outcomes. // if there are no generic constraints - only object methods can be called, they are handled in BurstReferenceExpressionAnalyzer. // If there is some interface constraint - then it is ok, Burst allows to call interface methods if they are implemented with struct. // CallGraph would have edges to interface through constraints, not instantiation. //else // if condional qualifier is class // if conditiinal qualifier is class instance // return // REASON: I will highlight refereceExpression, which would have ReadAccess. Burst can't access // managed objects. // else // if function non static // then it would be highlighted as error // else // ok. burst allows invoking static functions. // else // if conditional qualifier is struct instance // if function is virtual/abstract/override // HIGHLIGHT: invocation expressio WITHOUT parameters // ALSO: struct's method are implicitle sealed! // REASON: burst does not support any invocations that use virtual table. // IMPORTANT: type parameters and open types may have some virtual invocations, // but burst generic system allows only structures/primitives to instatiate generics. // Structure/primitives DOES support some virtual methods from System.Object. // else // it is ok. burst allows any method from structure // else // if function non static // then it would be highlighted as error // else // ok. burst alows invoking static functions. var invokedMethod = CallGraphUtil.GetCallee(invocationExpression) as IMethod; if (invokedMethod == null) { return(false); } if (IsDebugLog(invokedMethod)) { var argumentList = invocationExpression.ArgumentList.Arguments; if (argumentList.Count != 1) { return(false); } var argument = argumentList[0]; if (IsBurstPermittedString(argument.Expression?.Type())) { return(false); } consumer?.AddHighlighting(new BurstDebugLogInvalidArgumentWarning(argument.Expression.GetDocumentRange())); return(true); } if (IsStringFormat(invokedMethod)) { var argumentList = invocationExpression.ArgumentList.Arguments; var isWarningPlaced = BurstStringLiteralOwnerAnalyzer.CheckAndAnalyze(invocationExpression, new BurstManagedStringWarning(invocationExpression.GetDocumentRange()), consumer); if (isWarningPlaced) { return(true); } if (argumentList.Count == 0) { return(false); } var firstArgument = argumentList[0]; var cSharpLiteralExpression = firstArgument.Expression as ICSharpLiteralExpression; if (cSharpLiteralExpression != null && cSharpLiteralExpression.Literal.GetTokenType().IsStringLiteral) { return(false); } consumer?.AddHighlighting(new BurstDebugLogInvalidArgumentWarning(firstArgument.Expression.GetDocumentRange())); return(true); } if (IsObjectMethodInvocation(invocationExpression)) { consumer?.AddHighlighting(new BurstAccessingManagedMethodWarning(invocationExpression.GetDocumentRange(), invokedMethod.ShortName, invokedMethod.GetContainingType()?.ShortName)); return(true); } if (IsReturnValueBurstProhibited(invokedMethod) || HasBurstProhibitedArguments(invocationExpression.ArgumentList)) { consumer?.AddHighlighting(new BurstFunctionSignatureContainsManagedTypesWarning(invocationExpression.GetDocumentRange(), invokedMethod.ShortName)); return(true); } return(false); }
public virtual bool IsCalleeMarked(ICSharpExpression expression, DaemonProcessKind processKind) { return(IsMarked(CallGraphUtil.GetCallee(expression), processKind)); }