private static void WriteClosureStructBodies(Type[] typeDatas, StringBuilder sb, CrRuntimeLibrary crRuntime) { foreach (var typeData in typeDatas) { var mappedType = typeData.GetMappedType(); if (!mappedType.IsGenericType) { sb.AppendFormat("struct {0}; ", mappedType.ToCppMangling()).AppendLine(); } } foreach (var typeData in typeDatas) { if (DelegateManager.IsTypeDelegate(typeData)) { continue; } var type = typeData.GetMappedType(); var mappedType = typeData; if (mappedType.IsGenericType) { var genericTypeCount = mappedType.GetGenericArguments().Length; var typeNames = new List <string>(); for (var i = 1; i <= genericTypeCount; i++) { typeNames.Add("class T" + i); } sb.AppendFormat("template <{0}> ", string.Join(", ", typeNames)).AppendLine(); } if (!type.IsValueType && type.BaseType != null) { sb.AppendFormat("struct {0} : public {1} {{", type.ToCppMangling(), type.BaseType.ToCppMangling()); } else { sb.AppendFormat("struct {0} {{", type.ToCppMangling()); } sb.AppendLine(); if (type == typeof(object)) { sb.AppendLine("int _typeId;"); } WriteClassFieldsBody(sb, mappedType, crRuntime); sb.AppendFormat("}};").AppendLine(); var typedesc = UsedTypeList.Set(type, crRuntime); typedesc.WriteStaticFieldInitialization(sb); } }
public static Dictionary <int, bool> EscapingParameterData(this MethodBase info, CrRuntimeLibrary crRuntime) { var interpreter = info.GetInterpreter(crRuntime); if (interpreter == null) { return(null); } var calledMethod = interpreter.MidRepresentation; var otherMethodData = (Dictionary <int, bool>)calledMethod.GetAdditionalProperty(EscapeName); if (otherMethodData == null) { return(null); } return(otherMethodData); }
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); }
public static bool ReadPurity(MethodBase methodBase, CrRuntimeLibrary crRuntime) { var method = methodBase.GetInterpreter(crRuntime); return(AnalyzeFunctionPurity.ReadPurity(method)); }
public static MethodInterpreter GetInterpreter(this MethodData methodData, CrRuntimeLibrary crRuntime) { var methodBase = methodData.Info; return(GetInterpreter(methodBase, crRuntime)); }
public static void SortTypeClosure(List <Type> types, CrRuntimeLibrary crRuntime) { var typeComparer = new ClosureTypeComparer(types, crRuntime); typeComparer.Sort(); }
public static void RemoveCandidatesIfEscapes(LocalVariable localVariable, HashSet <LocalVariable> candidateVariables, LocalOperation op, CrRuntimeLibrary crRuntime) { switch (op.Kind) { case OperationKind.Assignment: HandleAssign(candidateVariables, op); break; case OperationKind.Return: HandleReturn(localVariable, candidateVariables, op); break; case OperationKind.Call: case OperationKind.CallVirtual: case OperationKind.CallInterface: HandleCall(localVariable, candidateVariables, op, crRuntime); break; case OperationKind.BinaryOperator: case OperationKind.UnaryOperator: case OperationKind.BranchOperator: case OperationKind.GetArrayItem: case OperationKind.GetField: break; case OperationKind.SetArrayItem: HandleSetArrayItem(candidateVariables, op); break; case OperationKind.SetField: HandleSetArrayItem(candidateVariables, op); break; case OperationKind.RefAssignment: HandleRefAssignment(localVariable, candidateVariables, op); break; case OperationKind.FieldRefAssignment: break; default: throw new NotImplementedException(); } }
private static void HandleLoadFunctionInstructions(Dictionary <MethodInterpreterKey, MethodInterpreter> result, LocalOperation[] localOperations, List <MethodInterpreter> toAdd, CrRuntimeLibrary crRuntime) { if (localOperations.Length == 0) { return; } foreach (var localOperation in localOperations) { var functionPointer = (FunctionPointerStore)localOperation.Value; var info = functionPointer.FunctionPointer; var interpreter = info.GetInterpreter(crRuntime); if (interpreter == null) { continue; } result[interpreter.ToKey()] = interpreter; toAdd.Add(interpreter); } }
public static List <MethodInterpreter> GetMethodClosure(this MethodInterpreter entryPoints, CrRuntimeLibrary crRuntime) { return(GetClosureDictionary(entryPoints, crRuntime).Values.ToList()); }
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 Type ReversedType(this Type type, CrRuntimeLibrary crRuntime) { return(crRuntime.GetReverseType(type) ?? type); }
private static bool WriteParametersToSb(MethodData operationData, MethodBase methodInfo, StringBuilder sb, MethodInterpreter interpreter, CrRuntimeLibrary crRuntime) { var identifierValues = operationData.Parameters; var escapingData = methodInfo.BuildEscapingBools(crRuntime); if (escapingData == null) { var argumentsCall = String.Join(", ", identifierValues.Select(p => { var computeValue = p.ComputedValue(); return(computeValue); })); sb.AppendFormat("({0});", argumentsCall); return(true); } #region Parameters sb.Append("("); var pos = 0; var isFirst = true; var argumentUsages = operationData.Interpreter.AnalyzeProperties.GetUsedArguments( operationData.Interpreter.MidRepresentation.Vars.Arguments); var argumentTypes = operationData.Info.GetMethodArgumentTypes(); for (var index = 0; index < identifierValues.Count; index++) { var value = identifierValues[index]; if (!argumentUsages[index]) { continue; } 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 = interpreter.AnalyzeProperties.GetVariableData(localValue); switch (localValueData) { 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 return(false); }
public static HashSet <Type> GetTypesClosure(List <MethodInterpreter> methodList, out bool foundNewMethods, ProgramClosure programClosure, CrRuntimeLibrary crRuntime) { var typesSet = ScanMethodParameters(methodList, crRuntime); //For struct types we need to add them separately foreach (var methodInterpreter in methodList) { foreach (var operation in methodInterpreter.MidRepresentation.LocalOperations) { if (operation is Assignment) { var type = (operation as Assignment).AssignedTo.FixedType.ClrType; if (!typesSet.Contains(type) && !type.IsByRef) { typesSet.Add(type); } } if (operation is RefAssignment) { var type = (operation as RefAssignment).Left.FixedType.ClrType; if (!typesSet.Contains(type) && !type.IsByRef) { typesSet.Add(type); } } } } foundNewMethods = false; var resultTypes = BuildScannedDictionaryFromTypesAndInstructions(typesSet, crRuntime); var methodDict = methodList.ToDictionary(method => method.Method.Register(crRuntime).ToKey()); var virtMethods = methodList.Where(m => m.Method.IsVirtual).ToArray(); foreach (var virt in virtMethods) { var baseClass = virt.Method.DeclaringType; var methodName = virt.Method.Name; var methodArgs = virt.Method.GetParameters().Select(par => par.ParameterType).ToArray(); foreach (var type in resultTypes) { var hasinterface = false;//TODO: for some reason I cannot use .Contains / Linq here ? foreach (var @interface in type.GetInterfaces()) { if (@interface == baseClass) { hasinterface = true; // methodName = baseClass.Name +"."+methodName; break; } } if ((!(type.IsSubclassOf(baseClass) || hasinterface))) { continue; } MethodInfo implMethod; if (!hasinterface) { implMethod = type.GetMethod(methodName, methodArgs); } else { implMethod = type.GetInterfaceMap(baseClass) .InterfaceMethods.Where(m => m.Name == methodName && (!m.GetParameters().Select(j => j.ParameterType).Except(methodArgs).Any())).FirstOrDefault(); } if (methodDict.ContainsKey(implMethod.Register(crRuntime).ToKey())) { continue; } var implInterpreter = implMethod.Register(); MetaLinker.Interpret(implInterpreter, crRuntime); methodList.Add(implInterpreter); foundNewMethods = true; } } return(resultTypes); }
private static HashSet <Type> ScanMethodParameters(List <MethodInterpreter> closure, CrRuntimeLibrary crRuntime) { var typesSet = new HashSet <Type>(); foreach (var interpreter in closure) { var method = interpreter.Method; foreach (var parameter in method.GetParameters()) { var parameterType = parameter.ParameterType; if (parameterType.IsSubclassOf(typeof(Array))) { continue; } if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); } typesSet.Add(parameterType.GetReversedType(crRuntime)); } typesSet.Add(method.DeclaringType.GetReversedType(crRuntime)); } return(typesSet); }
private static void WriteClassFieldsBody(StringBuilder sb, Type mappedType, CrRuntimeLibrary crRuntime) { var typeDesc = UsedTypeList.Set(mappedType, crRuntime); typeDesc.WriteLayout(sb); }
public static void UpdateMethodEntryClosure(MethodInterpreter entryPoint, Dictionary <MethodInterpreterKey, MethodInterpreter> result, CrRuntimeLibrary crRuntime) { var useDef = entryPoint.MidRepresentation.UseDef; entryPoint.MidRepresentation.UpdateUseDef(); var ops = useDef.GetLocalOperations(); var callList = useDef.GetOperationsOfKind(OperationKind.Call).ToList(); callList.AddRange(useDef.GetOperationsOfKind(OperationKind.CallVirtual)); callList.AddRange(useDef.GetOperationsOfKind(OperationKind.CallInterface)); var localOperations = callList.Select(i => ops[i]).ToArray(); var toAdd = HandleCallInstructions(result, localOperations, crRuntime); var funcList = useDef.GetOperationsOfKind(OperationKind.LoadFunction).ToList(); localOperations = funcList.Select(i => ops[i]).ToArray(); HandleLoadFunctionInstructions(result, localOperations, toAdd, crRuntime); HandleTypeInitializers(result, toAdd, crRuntime); HandleGenerics(result, toAdd, crRuntime); }
public static StringBuilder GenerateSourceStringBuilder(MethodInterpreter interpreter, List <Type> typeClosure, List <MethodInterpreter> closure, VirtualMethodTable typeTable, CrRuntimeLibrary crRuntime) { var sb = new StringBuilder(); sb.AppendLine("#include \"sloth.h\""); var virtualMethodTableCodeWriter = new VirtualMethodTableCodeWriter(typeTable, closure); WriteClosureStructBodies(typeClosure.ToArray(), sb, crRuntime); WriteClosureDelegateBodies(closure, sb); WriteClosureHeaders(closure, sb, crRuntime); sb.AppendLine("#include \"runtime_base.hpp\""); sb.AppendLine(virtualMethodTableCodeWriter.GenerateTypeTableCode()); WriteCppMethods(closure, sb); WriteClosureMethods(closure, sb, typeTable.TypeTable, crRuntime); WriteMainBody(interpreter, sb); sb.AppendLine(PlatformInvokeCodeWriter.LoadDllMethods()); sb.AppendLine(ConstByteArrayList.BuildConstantTable()); sb.AppendLine(LinkingData.Instance.Strings.BuildStringTable()); return(sb); }
private static HashSet <Type> BuildScannedDictionaryFromTypesAndInstructions(HashSet <Type> typesSet, CrRuntimeLibrary crRuntime) { bool isAdded; do { var toAdd = new HashSet <Type>(typesSet); foreach (var type in typesSet) { AddBaseTypesToHash(type, toAdd); var mappedType = crRuntime.GetMappedType(type); if (type.IsPrimitive) { continue; } var fieldTypes = UsedTypeList.GetFieldTypeDependencies(type); toAdd.AddRange(fieldTypes); var fields = mappedType.GetFields().ToList(); fields.AddRange(mappedType.GetFields( BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)); foreach (var fieldInfo in fields) { var fieldType = fieldInfo.FieldType; if (fieldType.IsInterface) { continue; } if (fieldType.IsSubclassOf(typeof(Array))) { fieldType = fieldType.GetElementType(); } if (fieldType.IsPointer || fieldType.IsByRef) { fieldType = fieldType.GetElementType(); } var typeDesc = UsedTypeList.Set(type, crRuntime); if (typeDesc == null) { continue; } toAdd.Add(fieldType); AddBaseTypesToHash(fieldType, toAdd); } } isAdded = (toAdd.Count != typesSet.Count); typesSet = toAdd; } while (isAdded); var typesClosure = typesSet.Where(t => IsRefClassType(t) && !t.IsInterface).ToList(); foreach (var type in typesClosure) { UsedTypeList.Set(type, crRuntime); } typesSet.Remove(typeof(void)); typesSet.Remove(typeof(IntPtr)); typesSet.Remove(typeof(Array)); // typesSet.RemoveWhere(t => t.IsInterface); Interfaces should be treated as classes typesSet.RemoveWhere(t => t.IsPrimitive); typesSet.RemoveWhere(t => t.IsSubclassOf(typeof(Array))); typesSet.RemoveWhere(t => t.GetMappedType() == t && string.IsNullOrEmpty(t.FullName)); return(typesSet); }