private static void HandleNewArray(LocalOperation operation, StringBuilder bodySb, MidRepresentationVariables vars) { var assignment = (Assignment)operation.Value; var arrayData = (NewArrayObject)assignment.Right; var assignedData = vars.GetVariableData(assignment.AssignedTo); switch (assignedData.Escaping) { case EscapingMode.Stack: bodySb.AppendFormat("Array <{1}> {0} ({2}); ", assignment.AssignedTo.Name, arrayData.TypeArray.ToCppName(), arrayData.ArrayLength.Name); break; default: bodySb.AppendFormat("{0} = std::make_shared< Array <{1}> >({2}); ", assignment.AssignedTo.Name, arrayData.TypeArray.ToCppName(), arrayData.ArrayLength.Name); break; } }
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()); } }
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 AddVariableContent(StringBuilder variablesSb, string format, LocalVariable localVariable, MidRepresentationVariables vars, MethodInterpreter interpreter) { var localVariableData = interpreter.AnalyzeProperties.GetVariableData(localVariable); if (localVariableData == EscapingMode.Stack) { return; } if (localVariable.ComputedType().ClrType.IsSubclassOf(typeof(MethodInfo))) { variablesSb .AppendFormat("void (*{0})({1});", localVariable.Name, ComputeCommaSeparatedParameterTypes(localVariable)) .AppendLine(); return; } if (localVariableData == EscapingMode.Pointer) { var cppName = localVariable.ComputedType() .ClrType.ToDeclaredVariableType(true, localVariableData); variablesSb .AppendFormat(format, cppName, localVariable.Id) .AppendLine(); return; } variablesSb .AppendFormat(format, localVariable.ComputedType() .ClrType.ToDeclaredVariableType(true, localVariableData), localVariable.Id) .AppendLine(); }
static bool HandleCallOperations(MidRepresentationVariables vars, MethodInterpreter interpreter, ClosureEntities crRuntime, LocalOperation operation, CodeOutput bodySb) { switch (operation.Kind) { case OperationKind.Call: CppHandleCalls.HandleCall(operation, bodySb, vars, interpreter, crRuntime); break; case OperationKind.CallInterface: CppHandleCalls.HandleCallInterface(operation, bodySb, vars, interpreter, crRuntime); break; case OperationKind.CallVirtual: CppHandleCalls.HandleCallVirtual(operation, bodySb, interpreter, crRuntime); break; case OperationKind.CallRuntime: CppHandleCalls.HandleCallRuntime(operation, bodySb, crRuntime); break; default: return(false); } return(true); }
static void OptimizeUnusedVregs(HashSet <int> vregConstants, MidRepresentationVariables variables) { if (vregConstants.Count == 0) { return; } var liveVRegs = variables.VirtRegs.Where( vreg => vreg.Kind != VariableKind.Vreg || !vregConstants.Contains(vreg.Id)).ToList(); variables.VirtRegs = liveVRegs; }
private static void OptimizeUnusedLocals(HashSet <int> localConstants, MidRepresentationVariables variables) { if (localConstants.Count == 0) { return; } foreach (var localUnused in localConstants) { variables.LocalVars.RemoveAll(local => local.Id == localUnused); } }
public static void HandleCallInterface(LocalOperation operation, StringBuilder sbCode, MidRepresentationVariables vars, MethodInterpreter interpreter, ClosureEntities crRuntime) { var operationData = (CallMethodStatic)operation; var sb = new StringBuilder(); var methodInfo = operationData.Info.GetReversedMethod(crRuntime); var isVoidMethod = methodInfo.GetReturnType().IsVoid(); if (!isVoidMethod && operationData.Result != null) { sb.AppendFormat("{0} = ", operationData.Result.Name); } sb.AppendFormat("{0}_icall", methodInfo.ClangMethodSignature(crRuntime)); WriteParametersToSb(operationData, sb, interpreter); sbCode.Append(sb); }
public static void HandleCallVirtual(LocalOperation operation, StringBuilder sbCode, MidRepresentationVariables vars, MethodInterpreter interpreter, CrRuntimeLibrary crRuntime) { var operationData = (MethodData)operation.Value; var sb = new StringBuilder(); var methodInfo = operationData.Info.GetReversedMethod(); var isVoidMethod = methodInfo.GetReturnType().IsVoid(); if (!isVoidMethod && operationData.Result != null) { sb.AppendFormat("{0} = ", operationData.Result.Name); } sb.AppendFormat("{0}_vcall", methodInfo.ClangMethodSignature()); if (WriteParametersToSb(operationData, methodInfo, sb, interpreter, crRuntime)) { return; } sbCode.Append(sb); }
public static void HandleCall(LocalOperation operation, StringBuilder sbCode, MidRepresentationVariables vars) { var operationData = (MethodData)operation.Value; var sb = new StringBuilder(); var methodInfo = operationData.Info.GetReversedMethod(); #region Write method name var isVoidMethod = methodInfo.GetReturnType().IsVoid(); if (isVoidMethod) { sb.AppendFormat("{0}", methodInfo.ClangMethodSignature()); } else { if (operationData.Result == null) { sb.AppendFormat("{0}", methodInfo.ClangMethodSignature()); } else { sb.AppendFormat("{1} = {0}", methodInfo.ClangMethodSignature(), operationData.Result.Name); } } var identifierValues = operationData.Parameters; var escapingData = CppFullFileMethodWriter.BuildEscapingBools(methodInfo); if (escapingData == null) { var argumentsCall = String.Join(", ", identifierValues.Select(p => { var computeValue = p.ComputedValue(); return(computeValue); })); sb.AppendFormat("({0});", argumentsCall); return; } #endregion sb.Append("("); #region Parameters var pos = 0; var isFirst = true; var argumentTypes = operationData.Info.GetMethodArgumentTypes(); foreach (var value in identifierValues) { if (isFirst) { isFirst = false; } else { sb.Append(", "); } var localValue = value as LocalVariable; var argumentData = argumentTypes[pos]; var isEscaping = escapingData[pos]; pos++; if (localValue == null) { sb.Append(value.ComputedValue()); continue; } if (localValue.Kind == VariableKind.Argument) { } if (localValue.ComputedType().ClrType == typeof(IntPtr)) { var argumentTypeCast = argumentData.ToCppMangling(); sb.AppendFormat("({0}){1}", argumentTypeCast, localValue.Name); continue; } var localValueData = vars.GetVariableData(localValue); switch (localValueData.Escaping) { case EscapingMode.Smart: if (!isEscaping && localValue.ComputedType().ClrType.IsClass) { sb.AppendFormat("{0}.get()", localValue.Name); } else { sb.AppendFormat("{0}", localValue.Name); } continue; case EscapingMode.Stack: sb.AppendFormat("&{0}", localValue.Name); continue; case EscapingMode.Pointer: sb.AppendFormat(!isEscaping ? "{0}" : "{0}.get()", localValue.Name); continue; } } sb.Append(");"); #endregion sbCode.Append(sb); }
private static StringBuilder ComputeBodySb(List <LocalOperation> operations, MidRepresentationVariables vars, TypeDescriptionTable typeTable, MethodInterpreter interpreter, CrRuntimeLibrary crRuntime) { var bodySb = new StringBuilder(); foreach (var operation in operations) { if (CppHandleOperators.HandleAssignmentOperations(vars, bodySb, operation, operation.Kind, typeTable, interpreter)) { bodySb.AppendLine(); continue; } switch (operation.Kind) { case OperationKind.Label: WriteLabel(bodySb, (int)operation.Value); break; case OperationKind.AlwaysBranch: HandleAlwaysBranchOperator(operation, bodySb); break; case OperationKind.BranchOperator: CppHandleBranches.HandleBranchOperator(operation, bodySb); break; case OperationKind.Call: CppHandleCalls.HandleCall(operation, bodySb, vars, interpreter, crRuntime); break; case OperationKind.CallInterface: CppHandleCalls.HandleCallInterface(operation, bodySb, vars, interpreter, crRuntime); break; case OperationKind.CallVirtual: CppHandleCalls.HandleCallVirtual(operation, bodySb, vars, interpreter, crRuntime); break; case OperationKind.CallRuntime: CppHandleCalls.HandleCallRuntime(operation, bodySb); break; case OperationKind.Return: CppHandleCalls.HandleReturn(operation, bodySb); break; case OperationKind.CopyArrayInitializer: HandleCopyArrayInitializer(operation, bodySb); break; case OperationKind.Switch: HandleSwitch(operation, bodySb); break; case OperationKind.Comment: HandleComment(operation.Value.ToString(), bodySb); break; default: throw new InvalidOperationException( string.Format( "Invalid operation '{0}' is introduced in intermediary representation\nValue: {1}", operation.Kind, operation.Value)); } bodySb.AppendLine(); } bodySb.AppendLine("}"); return(bodySb); }
static CodeOutput ComputeBodySb(List <LocalOperation> operations, MidRepresentationVariables vars, TypeDescriptionTable typeTable, MethodInterpreter interpreter, ClosureEntities crRuntime) { var bodySb = new CodeOutput(); foreach (var operation in operations) { bodySb.Append("\n"); if (CppHandleOperators.HandleAssignmentOperations(bodySb, operation, operation.Kind, typeTable, interpreter, crRuntime)) { continue; } if (CppCastRelatedOperations.HandleCastRelatedOperations(typeTable, crRuntime, operation, bodySb, operation.Kind)) { continue; } if (HandleCallOperations(vars, interpreter, crRuntime, operation, bodySb)) { continue; } switch (operation.Kind) { case OperationKind.Label: WriteLabel(bodySb, ((Label)operation).JumpTo); break; case OperationKind.AlwaysBranch: HandleAlwaysBranchOperator(operation, bodySb); break; case OperationKind.BranchOperator: CppHandleBranches.HandleBranchOperator(operation, bodySb); break; case OperationKind.Return: CppHandleCalls.HandleReturn(operation, bodySb, interpreter); break; case OperationKind.CopyArrayInitializer: HandleCopyArrayInitializer(operation, bodySb); break; case OperationKind.Switch: HandleSwitch(operation, bodySb); break; case OperationKind.Comment: HandleComment(operation.ToString(), bodySb); break; default: throw new InvalidOperationException( $"Invalid operation '{operation.Kind}' is introduced in intermediary representation\nValue: {operation}"); } } return(bodySb); }
private static void HandleNewObject(LocalOperation operation, StringBuilder bodySb, MidRepresentationVariables vars) { 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 = vars.GetVariableData(value.AssignedTo); switch (assignedData.Escaping) { case EscapingMode.Stack: bodySb .AppendFormat("{1} {0};", value.AssignedTo.Name, cppName) .AppendLine(); break; default: bodySb .AppendFormat("{0} = std::make_shared<{1}>();", value.AssignedTo.Name, cppName) .AppendLine();; break; } }
private static void HandleLoadField(LocalOperation operation, StringBuilder bodySb, MidRepresentationVariables vars) { var fieldGetterInfo = (FieldGetter)operation.Value; var assignedFrom = fieldGetterInfo.Instance; var assignedFromData = vars.GetVariableData(assignedFrom); var isOnStack = assignedFromData.Escaping == EscapingMode.Stack; var fieldText = String.Format(isOnStack ? "{0}.{1}" : "{0}->{1}", fieldGetterInfo.Instance.Name, fieldGetterInfo.FieldName.ValidName()); var assignedTo = fieldGetterInfo.AssignedTo; var assignedToData = vars.GetVariableData(assignedTo); switch (assignedToData.Escaping) { case EscapingMode.Smart: bodySb.AppendFormat("{0} = {1};", assignedTo.Name, fieldText); break; case EscapingMode.Pointer: bodySb.AppendFormat("{0} = {1}.get();", assignedTo.Name, fieldText); break; } }
private static void HandleReadArrayItem(LocalOperation operation, StringBuilder bodySb, MidRepresentationVariables vars) { var value = (Assignment)operation.Value; var valueSrc = (ArrayVariable)value.Right; var parentType = valueSrc.Parent.ComputedType(); var variableData = vars.GetVariableData(value.AssignedTo); switch (variableData.Escaping) { 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; } }
public static bool HandleAssignmentOperations(MidRepresentationVariables vars, StringBuilder bodySb, LocalOperation operation, OperationKind kind) { switch (kind) { case OperationKind.Assignment: HandleAssign(bodySb, operation, vars); break; case OperationKind.BinaryOperator: HandleOperator(operation.Value, bodySb); break; case OperationKind.UnaryOperator: HandleUnaryOperator((UnaryOperator)operation.Value, bodySb); break; case OperationKind.SetField: HandleSetField(operation, bodySb); break; case OperationKind.GetField: HandleLoadField(operation, bodySb, vars); break; case OperationKind.SetStaticField: HandleSetStaticField(operation, bodySb); break; case OperationKind.GetStaticField: HandleLoadStaticField(operation, bodySb); break; case OperationKind.GetArrayItem: HandleReadArrayItem(operation, bodySb, vars); break; case OperationKind.NewObject: HandleNewObject(operation, bodySb, vars); break; case OperationKind.NewArray: HandleNewArray(operation, bodySb, vars); break; case OperationKind.AddressOfArrayItem: HandleGetAddressOfArrayItem(operation, bodySb); break; case OperationKind.RefAssignment: HandleRefAssignment(operation, bodySb); break; case OperationKind.DerefAssignment: HandleDerefAssignment(operation, bodySb); break; case OperationKind.FieldRefAssignment: HandleFieldRefAssignment(operation, bodySb); break; case OperationKind.LoadFunction: HandleLoadFunction(operation, bodySb); break; case OperationKind.SizeOf: HandleSizeOf(operation, bodySb); break; default: return(false); } return(true); }
private static StringBuilder ComputeBodySb(List <LocalOperation> operations, MidRepresentationVariables vars, TypeDescriptionTable typeTable, MethodInterpreter interpreter, ClosureEntities crRuntime) { var bodySb = new StringBuilder(); foreach (var operation in operations) { if (CppHandleOperators.HandleAssignmentOperations(bodySb, operation, operation.Kind, typeTable, interpreter, crRuntime)) { bodySb.AppendLine(); continue; } switch (operation.Kind) { case OperationKind.Label: WriteLabel(bodySb, ((Label)operation).JumpTo); break; case OperationKind.AlwaysBranch: HandleAlwaysBranchOperator(operation, bodySb); break; case OperationKind.BranchOperator: CppHandleBranches.HandleBranchOperator(operation, bodySb); break; case OperationKind.Call: CppHandleCalls.HandleCall(operation, bodySb, vars, interpreter, crRuntime); break; case OperationKind.CallInterface: CppHandleCalls.HandleCallInterface(operation, bodySb, vars, interpreter, crRuntime); break; case OperationKind.CallVirtual: CppHandleCalls.HandleCallVirtual(operation, bodySb, interpreter, crRuntime); break; case OperationKind.CallRuntime: CppHandleCalls.HandleCallRuntime(operation, bodySb, crRuntime); break; case OperationKind.Return: CppHandleCalls.HandleReturn(operation, bodySb, interpreter); break; case OperationKind.CopyArrayInitializer: HandleCopyArrayInitializer(operation, bodySb); break; case OperationKind.Switch: HandleSwitch(operation, bodySb); break; case OperationKind.Comment: HandleComment(operation.ToString(), bodySb); break; case OperationKind.Box: var boxing = crRuntime.FindFeature("Boxing"); if (!boxing.IsUsed) { boxing.IsUsed = true; boxing.Declarations.Add(@"template<class T> struct BoxedT : public System_Object { T Data; }; template<class T> std::shared_ptr<System_Object> box_value(T value, int typeId){ auto result = std::make_shared<BoxedT< T > >(); result->_typeId = typeId; result->Data = value; return result; } template<class T> T unbox_value(std::shared_ptr<System_Object> value){ auto resultObject = value.get(); auto castedUnboxing = (BoxedT<T>*)resultObject; return castedUnboxing->Data; }"); } HandleBox((Boxing)operation, bodySb, typeTable, crRuntime); break; case OperationKind.CastClass: HandleCastClass((ClassCasting)operation, bodySb, crRuntime); break; case OperationKind.Unbox: HandleUnbox((Unboxing)operation, bodySb, crRuntime); break; case OperationKind.IsInstance: HandleIsInstance((IsInstance)operation, bodySb, crRuntime); break; default: throw new InvalidOperationException( string.Format( "Invalid operation '{0}' is introduced in intermediary representation\nValue: {1}", operation.Kind, operation)); } bodySb.AppendLine(); } bodySb.AppendLine("}"); return(bodySb); }