Example #1
0
        public void CompileMethod(MethodDesc method)
        {
            _compilation.Log.WriteLine("Compiling " + method.ToString());

            SpecialMethodKind kind = method.DetectSpecialMethodKind();

            if (kind != SpecialMethodKind.Unknown)
            {
                string specialMethodCode = CompileSpecialMethod(method, kind);
                _compilation.GetRegisteredMethod(method).MethodCode = specialMethodCode;
                return;
            }

            var methodIL = _compilation.GetMethodIL(method);

            if (methodIL == null)
            {
                return;
            }

            string methodCode;

            try
            {
                var ilImporter = new ILImporter(_compilation, this, method, methodIL);

                CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext;

                if (!_compilation.Options.NoLineNumbers)
                {
                    IEnumerable <ILSequencePoint> sequencePoints = typeSystemContext.GetSequencePointsForMethod(method);
                    if (sequencePoints != null)
                    {
                        ilImporter.SetSequencePoints(sequencePoints);
                    }
                }

                IEnumerable <LocalVariable> localVariables = typeSystemContext.GetLocalVariableNamesForMethod(method);
                if (localVariables != null)
                {
                    ilImporter.SetLocalVariables(localVariables);
                }

                IEnumerable <string> parameters = typeSystemContext.GetParameterNamesForMethod(method);
                if (parameters != null)
                {
                    ilImporter.SetParameterNames(parameters);
                }

                methodCode = ilImporter.Compile();
            }
            catch (Exception e)
            {
                _compilation.Log.WriteLine(e.Message + " (" + method + ")");

                methodCode = GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine;
            }

            _compilation.GetRegisteredMethod(method).MethodCode = methodCode;
        }
Example #2
0
        string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            StringBuilder builder = new StringBuilder();

            switch (kind)
            {
            case SpecialMethodKind.PInvoke:
            case SpecialMethodKind.RuntimeImport:
            {
                EcmaMethod ecmaMethod = method as EcmaMethod;

                string importName = kind == SpecialMethodKind.PInvoke ?
                                    method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetRuntimeImportEntryPointName();

                if (importName == null)
                {
                    importName = method.Name;
                }

                // TODO: hacky special-case
                if (importName != "memmove" && importName != "malloc")         // some methods are already declared by the CRT headers
                {
                    builder.AppendLine(GetCppMethodDeclaration(method, false, importName));
                }
                builder.AppendLine(GetCppMethodDeclaration(method, true));
                builder.AppendLine("{");
                builder.Append("    ");
                if (GetCppSignatureTypeName(method.Signature.ReturnType) != "void")
                {
                    builder.Append("return ");
                }

                builder.AppendLine("::" + importName + "(" + GetCppMethodCallParamList(method) + ");");
                builder.AppendLine("}");

                return(builder.ToString());
            }

            default:
                // TODO: hacky special-case
                if (method.Name == "BlockCopy")
                {
                    return(null);
                }

                return(GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine);
            }
        }
Example #3
0
        public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode)
        {
            MethodDesc method = methodCodeNodeNeedingCode.Method;

            _compilation.Log.WriteLine("Compiling " + method.ToString());

            SpecialMethodKind kind = method.DetectSpecialMethodKind();

            if (kind != SpecialMethodKind.Unknown)
            {
                string specialMethodCode = CompileSpecialMethod(method, kind);

                methodCodeNodeNeedingCode.SetCode(specialMethodCode, Array.Empty <Object>());
                return;
            }

            var methodIL = _compilation.GetMethodIL(method);

            if (methodIL == null)
            {
                return;
            }

            try
            {
                var ilImporter = new ILImporter(_compilation, this, method, methodIL);

                CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext;

                if (!_compilation.Options.NoLineNumbers)
                {
                    IEnumerable <ILSequencePoint> sequencePoints = typeSystemContext.GetSequencePointsForMethod(method);
                    if (sequencePoints != null)
                    {
                        ilImporter.SetSequencePoints(sequencePoints);
                    }
                }

                IEnumerable <ILLocalVariable> localVariables = typeSystemContext.GetLocalVariableNamesForMethod(method);
                if (localVariables != null)
                {
                    ilImporter.SetLocalVariables(localVariables);
                }

                IEnumerable <string> parameters = typeSystemContext.GetParameterNamesForMethod(method);
                if (parameters != null)
                {
                    ilImporter.SetParameterNames(parameters);
                }

                ilImporter.Compile(methodCodeNodeNeedingCode);
            }
            catch (Exception e)
            {
                _compilation.Log.WriteLine(e.Message + " (" + method + ")");

                var builder = new CppGenerationBuffer();
                builder.AppendLine();
                builder.Append(GetCppMethodDeclaration(method, true));
                builder.AppendLine();
                builder.Append("{");
                builder.Indent();
                builder.AppendLine();
                builder.Append("throw 0xC000C000;");
                builder.Exdent();
                builder.AppendLine();
                builder.Append("}");

                methodCodeNodeNeedingCode.SetCode(builder.ToString(), Array.Empty <Object>());
            }
        }
Example #4
0
        private string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            var builder = new CppGenerationBuffer();

            switch (kind)
            {
            case SpecialMethodKind.PInvoke:
            case SpecialMethodKind.RuntimeImport:
            {
                EcmaMethod ecmaMethod = method as EcmaMethod;

                string importName = kind == SpecialMethodKind.PInvoke ?
                                    method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetAttributeStringValue("System.Runtime", "RuntimeImportAttribute");

                if (importName == null)
                {
                    importName = method.Name;
                }

                MethodSignature methodSignature  = method.Signature;
                bool            slotCastRequired = false;

                MethodSignature externCSignature;
                if (_externCSignatureMap.TryGetValue(importName, out externCSignature))
                {
                    slotCastRequired = !externCSignature.Equals(method.Signature);
                }
                else
                {
                    _externCSignatureMap.Add(importName, methodSignature);
                    externCSignature = methodSignature;
                }

                builder.AppendLine();
                builder.Append(GetCppMethodDeclaration(method, true));
                builder.AppendLine();
                builder.Append("{");
                builder.Indent();

                if (slotCastRequired)
                {
                    AppendSlotTypeDef(builder, method);
                }

                builder.AppendLine();
                if (!method.Signature.ReturnType.IsVoid)
                {
                    builder.Append("return ");
                }

                if (slotCastRequired)
                {
                    builder.Append("((__slot__" + GetCppMethodName(method) + ")");
                }
                builder.Append("::");
                builder.Append(importName);
                if (slotCastRequired)
                {
                    builder.Append(")");
                }

                builder.Append("(");
                builder.Append(GetCppMethodCallParamList(method));
                builder.Append(");");
                builder.Exdent();
                builder.AppendLine();
                builder.Append("}");

                return(builder.ToString());
            }

            default:
                builder.AppendLine();
                builder.Append(GetCppMethodDeclaration(method, true));
                builder.AppendLine();
                builder.Append("{");
                builder.Indent();
                builder.AppendLine();
                builder.Append("throw 0xC000C000;");
                builder.Exdent();
                builder.AppendLine();
                builder.Append("}");

                return(builder.ToString());
            }
        }
Example #5
0
        private string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            StringBuilder builder = new StringBuilder();
            switch (kind)
            {
                case SpecialMethodKind.PInvoke:
                case SpecialMethodKind.RuntimeImport:
                    {
                        EcmaMethod ecmaMethod = method as EcmaMethod;

                        string importName = kind == SpecialMethodKind.PInvoke ?
                            method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetAttributeStringValue("System.Runtime", "RuntimeImportAttribute");

                        if (importName == null)
                            importName = method.Name;

                        MethodSignature methodSignature = method.Signature;
                        bool slotCastRequired = false;

                        MethodSignature externCSignature;
                        if (_externCSignatureMap.TryGetValue(importName, out externCSignature))
                        {
                            slotCastRequired = !externCSignature.Equals(method.Signature);
                        }
                        else
                        {
                            _externCSignatureMap.Add(importName, methodSignature);
                            externCSignature = methodSignature;
                        }

                        builder.AppendLine(GetCppMethodDeclaration(method, true));
                        builder.AppendLine("{");

                        if (slotCastRequired)
                        {
                            AppendSlotTypeDef(builder, method);
                        }

                        if (!method.Signature.ReturnType.IsVoid)
                        {
                            builder.Append("return ");
                        }

                        if (slotCastRequired)
                            builder.Append("((__slot__" + GetCppMethodName(method) + ")");
                        builder.Append("::");
                        builder.Append(importName);
                        if (slotCastRequired)
                            builder.Append(")");

                        builder.Append("(");
                        builder.Append(GetCppMethodCallParamList(method));
                        builder.AppendLine(");");
                        builder.AppendLine("}");

                        return builder.ToString();
                    }

                default:
                    return GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine;
            }
        }
Example #6
0
        private void CreateNodeCaches()
        {
            _typeSymbols = new NodeCache <TypeDesc, IEETypeNode>((TypeDesc type) =>
            {
                Debug.Assert(type.IsTypeDefinition || !type.HasSameTypeDefinition(ArrayOfTClass), "Asking for Array<T> EEType");

                if (_compilationModuleGroup.ContainsType(type))
                {
                    return(new EETypeNode(type, false));
                }
                else
                {
                    return(new ExternEETypeSymbolNode(type));
                }
            });

            _constructedTypeSymbols = new NodeCache <TypeDesc, IEETypeNode>((TypeDesc type) =>
            {
                Debug.Assert(type.IsTypeDefinition || !type.HasSameTypeDefinition(ArrayOfTClass), "Asking for Array<T> EEType");

                if (_compilationModuleGroup.ContainsType(type))
                {
                    return(new EETypeNode(type, true));
                }
                else
                {
                    return(new ExternEETypeSymbolNode(type));
                }
            });

            _nonGCStatics = new NodeCache <MetadataType, NonGCStaticsNode>((MetadataType type) =>
            {
                return(new NonGCStaticsNode(type, this));
            });

            _GCStatics = new NodeCache <MetadataType, GCStaticsNode>((MetadataType type) =>
            {
                return(new GCStaticsNode(type));
            });

            _GCStaticIndirectionNodes = new NodeCache <MetadataType, EmbeddedObjectNode>((MetadataType type) =>
            {
                ISymbolNode gcStaticsNode = TypeGCStaticsSymbol(type);
                Debug.Assert(gcStaticsNode is GCStaticsNode);
                return(GCStaticsRegion.NewNode((GCStaticsNode)gcStaticsNode));
            });

            _threadStatics = new NodeCache <MetadataType, ThreadStaticsNode>((MetadataType type) =>
            {
                return(new ThreadStaticsNode(type, this));
            });

            _GCStaticEETypes = new NodeCache <bool[], GCStaticEETypeNode>((bool[] gcdesc) =>
            {
                return(new GCStaticEETypeNode(gcdesc, this));
            }, new BoolArrayEqualityComparer());

            _readOnlyDataBlobs = new NodeCache <Tuple <string, byte[], int>, BlobNode>((Tuple <string, byte[], int> key) =>
            {
                return(new BlobNode(key.Item1, ObjectNodeSection.TextSection, key.Item2, key.Item3));
            }, new BlobTupleEqualityComparer());

            _externSymbols = new NodeCache <string, ExternSymbolNode>((string name) =>
            {
                return(new ExternSymbolNode(name));
            });

            _internalSymbols = new NodeCache <Tuple <ObjectNode, int, string>, ObjectAndOffsetSymbolNode>(
                (Tuple <ObjectNode, int, string> key) =>
            {
                return(new ObjectAndOffsetSymbolNode(key.Item1, key.Item2, key.Item3));
            });

            _methodEntrypoints = new NodeCache <MethodDesc, IMethodNode>((MethodDesc method) =>
            {
                if (!_cppCodeGen)
                {
                    SpecialMethodKind kind = method.DetectSpecialMethodKind();
                    if (kind == SpecialMethodKind.PInvoke)
                    {
                        return(new PInvokeMethodNode(method));
                    }
                    else if (kind == SpecialMethodKind.RuntimeImport)
                    {
                        return(new RuntimeImportMethodNode(method));
                    }
                }

                if (_compilationModuleGroup.ContainsMethod(method))
                {
                    if (_cppCodeGen)
                    {
                        return(new CppMethodCodeNode(method));
                    }
                    else
                    {
                        return(new MethodCodeNode(method));
                    }
                }
                else
                {
                    return(new ExternMethodSymbolNode(method));
                }
            });

            _unboxingStubs = new NodeCache <MethodDesc, IMethodNode>((MethodDesc method) =>
            {
                return(new UnboxingStubNode(method));
            });

            _virtMethods = new NodeCache <MethodDesc, VirtualMethodUseNode>((MethodDesc method) =>
            {
                return(new VirtualMethodUseNode(method));
            });

            _readyToRunHelpers = new NodeCache <Tuple <ReadyToRunHelperId, Object>, ReadyToRunHelperNode>((Tuple <ReadyToRunHelperId, Object> helper) =>
            {
                return(new ReadyToRunHelperNode(helper.Item1, helper.Item2));
            });

            _stringDataNodes = new NodeCache <string, StringDataNode>((string data) =>
            {
                return(new StringDataNode(data));
            });

            _stringIndirectionNodes = new NodeCache <string, StringIndirectionNode>((string data) =>
            {
                return(new StringIndirectionNode(data));
            });

            _typeOptionalFields = new NodeCache <EETypeOptionalFieldsBuilder, EETypeOptionalFieldsNode>((EETypeOptionalFieldsBuilder fieldBuilder) =>
            {
                return(new EETypeOptionalFieldsNode(fieldBuilder, this.Target));
            });

            _interfaceDispatchCells = new NodeCache <MethodDesc, InterfaceDispatchCellNode>((MethodDesc method) =>
            {
                return(new InterfaceDispatchCellNode(method));
            });

            _interfaceDispatchMaps = new NodeCache <TypeDesc, InterfaceDispatchMapNode>((TypeDesc type) =>
            {
                return(new InterfaceDispatchMapNode(type));
            });

            _interfaceDispatchMapIndirectionNodes = new NodeCache <TypeDesc, EmbeddedObjectNode>((TypeDesc type) =>
            {
                var dispatchMap = InterfaceDispatchMap(type);
                return(DispatchMapTable.NewNodeWithSymbol(dispatchMap, (indirectionNode) =>
                {
                    dispatchMap.SetDispatchMapIndex(this, DispatchMapTable.IndexOfEmbeddedObject(indirectionNode));
                }));
            });

            _eagerCctorIndirectionNodes = new NodeCache <MethodDesc, EmbeddedObjectNode>((MethodDesc method) =>
            {
                Debug.Assert(method.IsStaticConstructor);
                Debug.Assert(TypeInitializationManager.HasEagerStaticConstructor((MetadataType)method.OwningType));
                return(EagerCctorTable.NewNode(MethodEntrypoint(method)));
            });

            _vTableNodes = new NodeCache <TypeDesc, VTableSliceNode>((TypeDesc type ) =>
            {
                if (CompilationModuleGroup.ShouldProduceFullType(type))
                {
                    return(new EagerlyBuiltVTableSliceNode(type));
                }
                else
                {
                    return(new LazilyBuiltVTableSliceNode(type));
                }
            });

            _jumpThunks = new NodeCache <Tuple <ExternSymbolNode, ISymbolNode>, SingleArgumentJumpThunk>((Tuple <ExternSymbolNode, ISymbolNode> data) =>
            {
                return(new SingleArgumentJumpThunk(data.Item1, data.Item2));
            });
        }
 public void AddSpecialMethod(SpecialMethodKind setup, MethodInfo method)
 {
     mySpecialMethods[setup] = method;
 }
Example #8
0
        private string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            StringBuilder builder = new StringBuilder();
            switch (kind)
            {
                case SpecialMethodKind.PInvoke:
                case SpecialMethodKind.RuntimeImport:
                    {
                        EcmaMethod ecmaMethod = method as EcmaMethod;

                        string importName = kind == SpecialMethodKind.PInvoke ?
                            method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetAttributeStringValue("System.Runtime", "RuntimeImportAttribute");

                        if (importName == null)
                            importName = method.Name;

                        // TODO: hacky special-case
                        if (importName != "memmove" && importName != "malloc") // some methods are already declared by the CRT headers
                        {
                            builder.AppendLine(GetCppMethodDeclaration(method, false, importName));
                        }
                        builder.AppendLine(GetCppMethodDeclaration(method, true));
                        builder.AppendLine("{");
                        builder.Append("    ");
                        if (GetCppSignatureTypeName(method.Signature.ReturnType) != "void")
                        {
                            builder.Append("return ");
                        }

                        builder.AppendLine("::" + importName + "(" + GetCppMethodCallParamList(method) + ");");
                        builder.AppendLine("}");

                        return builder.ToString();
                    }

                default:
                    // TODO: hacky special-case
                    if (method.Name == "BlockCopy")
                        return null;

                    return GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine;
            }
        }
Example #9
0
        private string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            StringBuilder builder = new StringBuilder();

            switch (kind)
            {
            case SpecialMethodKind.PInvoke:
            case SpecialMethodKind.RuntimeImport:
            {
                EcmaMethod ecmaMethod = method as EcmaMethod;

                string importName = kind == SpecialMethodKind.PInvoke ?
                                    method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetAttributeStringValue("System.Runtime", "RuntimeImportAttribute");

                if (importName == null)
                {
                    importName = method.Name;
                }

                MethodSignature methodSignature  = method.Signature;
                bool            slotCastRequired = false;

                MethodSignature externCSignature;
                if (_externCSignatureMap.TryGetValue(importName, out externCSignature))
                {
                    slotCastRequired = !externCSignature.Equals(method.Signature);
                }
                else
                {
                    externCSignature = methodSignature;
                }

                // TODO: hacky special-case
                if (importName != "memmove" && importName != "malloc")         // some methods are already declared by the CRT headers
                {
                    builder.AppendLine(GetCppMethodDeclaration(method, false, importName, externCSignature));
                }
                builder.AppendLine(GetCppMethodDeclaration(method, true));
                builder.AppendLine("{");

                if (slotCastRequired)
                {
                    AppendSlotTypeDef(builder, method);
                }

                if (!method.Signature.ReturnType.IsVoid)
                {
                    builder.Append("return ");
                }

                if (slotCastRequired)
                {
                    builder.Append("((__slot__" + GetCppMethodName(method) + ")");
                }
                builder.Append("::");
                builder.Append(importName);
                if (slotCastRequired)
                {
                    builder.Append(")");
                }

                builder.Append("(");
                builder.Append(GetCppMethodCallParamList(method));
                builder.AppendLine(");");
                builder.AppendLine("}");

                return(builder.ToString());
            }

            default:
                return(GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine);
            }
        }