private static void AllocateVariablesOnStack(LocalOperation[] localOp, HashSet <LocalVariable> candidateVariables, MethodInterpreter interpreter) { var newOps = localOp.Where(op => op.Kind == OperationKind.NewArray || op.Kind == OperationKind.NewObject).ToArray(); if (newOps.Length == 0) { return; } foreach (var op in newOps) { var variable = op.GetDefinition(); if (variable == null) { continue; } if (!candidateVariables.Contains(variable)) { continue; } var variableData = interpreter.AnalyzeProperties.GetVariableData(variable); interpreter.AnalyzeProperties.SetVariableData(variable, EscapingMode.Stack); } }
public MethodData(MethodInterpreter interpreter) { Parameters = new List <IdentifierValue>(); Interpreter = interpreter; Info = interpreter.Method; }
public void WriteCodeToOutput(CodeOutput bodySb, MethodInterpreter interpreter) { bodySb.Append("\n"); if (Returning == null) { bodySb.Append("return;"); } else { //Need to expand this for more cases if (Returning is ConstValue) { var retType = interpreter.Method.GetReturnType(); if (retType == typeof(string)) { bodySb.AppendFormat("return {0};", Returning.ComputedValue()); } else { bodySb.AppendFormat("return {0};", Returning.Name); } } else { bodySb.AppendFormat("return {0};", Returning.Name); } } }
public override void OptimizeOperations(MethodInterpreter interpreter) { var useDef = interpreter.MidRepresentation.UseDef; var operations = useDef.GetLocalOperations(); var labelTable = useDef.GetLabelTable(true); var reached = new SortedSet <int>(); Interpret(0, operations, labelTable, reached); if (reached.Count == operations.Length) { return; } Result = true; var toDelete = new List <int>(); for (var i = 0; i < operations.Length; i++) { if (!reached.Contains(i)) { toDelete.Add(i); } } interpreter.DeleteInstructions(toDelete); }
private static void HandleReadArrayItem(LocalOperation operation, StringBuilder bodySb, MethodInterpreter interpreter) { var value = (Assignment)operation.Value; var valueSrc = (ArrayVariable)value.Right; var parentType = valueSrc.Parent.ComputedType(); var variableData = interpreter.AnalyzeProperties.GetVariableData(value.AssignedTo); switch (variableData) { case EscapingMode.Smart: bodySb.AppendFormat(parentType.ClrType.IsClass ? "{0} = (*{1})[{2}];" : "{0} = {1}[{2}];", value.AssignedTo.Name, valueSrc.Parent.Name, valueSrc.Index.Name); return; case EscapingMode.Pointer: bodySb.AppendFormat(parentType.ClrType.IsClass ? "{0} = ((*{1})[{2}]).get();" : "{0} = ({1}[{2}]).get();", value.AssignedTo.Name, valueSrc.Parent.Name, valueSrc.Index.Name); return; } }
private static void HandleNewObject(LocalOperation operation, StringBuilder bodySb, MidRepresentationVariables vars, TypeDescriptionTable typeTable, MethodInterpreter interpreter) { var value = (Assignment)operation.Value; var rightValue = (NewConstructedObject)value.Right; var localValue = rightValue.Info; var declaringType = localValue.DeclaringType; var cppName = declaringType.ToDeclaredVariableType(true, EscapingMode.Stack); var assignedData = interpreter.AnalyzeProperties.GetVariableData(value.AssignedTo); var isStack = assignedData == EscapingMode.Stack; if (isStack) { bodySb .AppendFormat("{1} {0};", value.AssignedTo.Name, cppName); } else { bodySb.AppendFormat("{0} = std::make_shared<{1}>();", value.AssignedTo.Name, cppName); } bodySb.AppendLine(); typeTable.SetIdOfInstance(bodySb, value.AssignedTo, declaringType, isStack); }
private static void HandleAssign(StringBuilder sb, LocalOperation operation, MidRepresentationVariables vars, TypeDescriptionTable typeTable, MethodInterpreter interpreter) { var assignment = (Assignment)operation.Value; if (assignment.Right is NewConstructedObject) { HandleNewObject(operation, sb, vars, typeTable, interpreter); return; } var assignedTo = assignment.AssignedTo; var localVariable = assignment.Right as LocalVariable; if (localVariable != null) { var leftVarType = assignment.AssignedTo.ComputedType(); var rightVarType = assignment.Right.ComputedType(); if (leftVarType != rightVarType) { if (rightVarType.ClrType.IsPointer) { sb.AppendFormat("{0} = *{1};", assignedTo, localVariable.Name); return; } } var assignedToData = interpreter.AnalyzeProperties.GetVariableData(assignedTo); var localVariableData = interpreter.AnalyzeProperties.GetVariableData(localVariable); var rightVar = localVariable; var description = assignedTo.ComputedType(); if (description.ClrTypeCode != TypeCode.Object || assignedToData == localVariableData) { sb.AppendFormat("{0} = {1};", assignedTo.Name, rightVar.Name); return; } switch (assignedToData) { case EscapingMode.Pointer: switch (localVariableData) { case EscapingMode.Stack: sb.AppendFormat("{0} = &{1};", assignedTo.Name, rightVar.Name); return; case EscapingMode.Smart: sb.AppendFormat("{0} = ({1}).get();", assignedTo.Name, rightVar.Name); return; } break; case EscapingMode.Smart: throw new InvalidDataException("Case not possible!"); } throw new InvalidDataException("Case not handled"); } else { sb.AppendFormat("{0} = {1};", assignedTo.Name, assignment.Right.ComputedValue()); } }
public override void OptimizeOperations(MethodInterpreter interpreter) { var midRepresentation = interpreter.MidRepresentation; var useDef = midRepresentation.UseDef; var operations = useDef.GetLocalOperations(); var localOps = midRepresentation.LocalOperations; var callIndices = useDef.GetOperationsOfKind(OperationKind.Call); foreach (var index in callIndices) { var op = operations[index]; var methodData = (MethodData)op.Value; var info = methodData.Info; if (!info.IsConstructor) { continue; } if (info.DeclaringType != typeof(object) && info.DeclaringType != interpreter.Method.DeclaringType) { continue; } if (methodData.Interpreter.MidRepresentation.LocalOperations.Count > 1) { continue; } localOps.RemoveAt(index); Result = true; return; } }
private void HandleInterpreterInstructions(MethodInterpreter interpreter, List <MethodInterpreter> methodInterpreters, List <Type> usedTypes) { var useDef = interpreter.MidRepresentation.UseDef; var calls = useDef.GetOperationsOfKind(OperationKind.CallVirtual).ToList(); var allOps = useDef.GetLocalOperations(); foreach (var callOp in calls) { var op = allOps[callOp]; var methodData = (MethodData)op.Value; var callingInterpreterKey = methodData.Interpreter.ToKey(); var declaringType = callingInterpreterKey.Interpreter.DeclaringType; var implementors = declaringType.ClrType.ImplementorsOfT(usedTypes); if (implementors.Count > 0) { continue; } op.Kind = OperationKind.Call; Result = true; } if (Result) { interpreter.MidRepresentation.UpdateUseDef(); } }
/// <inheritdoc/> internal override object Run() { var declarations = BaZicInterpreter.MethodDeclarations.Where(m => string.Compare(m.Name.Identifier, Expression.MethodName.Identifier, StringComparison.Ordinal) == 0); if (declarations.Count() == 0) { BaZicInterpreter.ChangeState(this, new MethodNotFoundException(Expression.MethodName.Identifier, L.BaZic.Runtime.Interpreters.Expressions.InvokeMethodInterpreter.FormattedMethodNotFound(Expression.MethodName)), Expression); return(null); } else if (declarations.Count() > 1) { BaZicInterpreter.ChangeState(this, new MethodNotFoundException(Expression.MethodName.Identifier, L.BaZic.Runtime.Interpreters.Expressions.InvokeMethodInterpreter.FormattedSeveralMethods(Expression.MethodName)), Expression); return(null); } // If the invocation is made manually by the user (outisde of the execution flow). if (_failIfNotExtern) { if (!declarations.Single().IsExtern) { BaZicInterpreter.ChangeState(this, new MethodNotFoundException(Expression.MethodName.Identifier, L.BaZic.Runtime.Interpreters.Expressions.InvokeMethodInterpreter.FormattedMethodNotFound(Expression.MethodName)), Expression); return(null); } if (!declarations.Single().IsAsync&& Expression.Await) { Expression.Await = false; } } var methodInterpreter = new MethodInterpreter(BaZicInterpreter, ParentInterpreter, declarations.Single(), Expression, _executionFlowId); return(methodInterpreter.Invoke()); }
public static HashSet <LocalVariable> GetAllUsedVariables(MethodInterpreter interpreter, bool includeDefinitions = false) { var useDef = interpreter.MidRepresentation.UseDef; return(GetAllUsedVariables(useDef, includeDefinitions)); }