Example #1
0
        private void OutputTypeNode(IEETypeNode typeNode, NodeFactory factory, CppGenerationBuffer forwardDefinitions, CppGenerationBuffer typeDefinitions, CppGenerationBuffer methodTable)
        {
            if (_emittedTypes == null)
            {
                _emittedTypes = new HashSet<TypeDesc>();
            }
            TypeDesc nodeType = typeNode.Type;
            if (nodeType.IsPointer || nodeType.IsByRef || _emittedTypes.Contains(nodeType))
                return;

            _emittedTypes.Add(nodeType);


            // Create Namespaces
            string mangledName = GetCppTypeName(nodeType);

            int nesting = 0;
            int current = 0;

            forwardDefinitions.AppendLine();
            for (;;)
            {
                int sep = mangledName.IndexOf("::", current);

                if (sep < 0)
                    break;

                if (sep != 0)
                {
                    // Case of a name not starting with ::
                    forwardDefinitions.Append("namespace " + mangledName.Substring(current, sep - current) + " { ");
                    typeDefinitions.Append("namespace " + mangledName.Substring(current, sep - current) + " { ");
                    typeDefinitions.Indent();
                    nesting++;
                }
                current = sep + 2;
            }

            forwardDefinitions.Append("class " + mangledName.Substring(current) + ";");

            // type definition
            typeDefinitions.Append("class " + mangledName.Substring(current));
            if (!nodeType.IsValueType)
            {
                // Don't emit inheritance if base type has not been marked for emission
                if (nodeType.BaseType != null && _emittedTypes.Contains(nodeType.BaseType))
                {
                    typeDefinitions.Append(" : public " + GetCppTypeName(nodeType.BaseType));
                }
            }
            typeDefinitions.Append(" {");
            typeDefinitions.AppendLine();
            typeDefinitions.Append("public:");
            typeDefinitions.Indent();

            // TODO: Enable once the dependencies are tracked for arrays
            // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked)
            if (!nodeType.IsPointer && !nodeType.IsByRef)
            {
                typeDefinitions.AppendLine();
                typeDefinitions.Append("static MethodTable * __getMethodTable();");
            }
            if (typeNode is ConstructedEETypeNode)
            {
                OutputTypeFields(typeDefinitions, nodeType);

                IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(nodeType).Slots;

                int baseSlots = 0;
                var baseType = nodeType.BaseType;
                while (baseType != null)
                {
                    IReadOnlyList<MethodDesc> baseVirtualSlots = _compilation.NodeFactory.VTable(baseType).Slots;
                    if (baseVirtualSlots != null)
                        baseSlots += baseVirtualSlots.Count;
                    baseType = baseType.BaseType;
                }

                for (int slot = 0; slot < virtualSlots.Count; slot++)
                {
                    MethodDesc virtualMethod = virtualSlots[slot];
                    typeDefinitions.AppendLine();
                    typeDefinitions.Append(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot));
                }

                if (nodeType.IsDelegate)
                {
                    typeDefinitions.AppendLine();
                    typeDefinitions.Append(GetCodeForDelegate(nodeType));
                }


                if (nodeType.HasStaticConstructor)
                {
                    _statics.AppendLine();
                    _statics.Append("bool __cctor_" + GetCppTypeName(nodeType).Replace("::", "__") + ";");
                }

                List<MethodDesc> methodList;
                if (_methodLists.TryGetValue(nodeType, out methodList))
                {
                    foreach (var m in methodList)
                    {
                        typeDefinitions.AppendLine();
                        AppendCppMethodDeclaration(typeDefinitions, m, false);
                    }
                }
            }
            typeDefinitions.AppendEmptyLine();
            typeDefinitions.Append("};");
            typeDefinitions.AppendEmptyLine();
            typeDefinitions.Exdent();

            while (nesting > 0)
            {
                forwardDefinitions.Append("};");
                typeDefinitions.Append("};");
                typeDefinitions.Exdent();
                nesting--;
            }
            typeDefinitions.AppendEmptyLine();

            // declare method table
            if (!nodeType.IsPointer && !nodeType.IsByRef)
            {
                methodTable.Append(GetCodeForObjectNode(typeNode as ObjectNode, factory));
                methodTable.AppendEmptyLine();
            }
        }
Example #2
0
        private void OutputType(CppGenerationBuffer sb, TypeDesc t, bool full)
        {
            _emittedTypes.Add(t);

            if (full)
            {
                if (!t.IsValueType)
                {
                    var baseType = t.BaseType;
                    if (baseType != null)
                    {
                        if (!_emittedTypes.Contains(baseType))
                        {
                            OutputType(sb, baseType, full);
                        }
                    }
                }

                foreach (var field in t.GetFields())
                {
                    var fieldType = GetFieldTypeOrPlaceholder(field);
                    if (fieldType.IsValueType && !fieldType.IsPrimitive && !field.IsStatic)
                    {
                        if (!_emittedTypes.Contains(fieldType))
                        {
                            OutputType(sb, fieldType, full);
                        }
                    }
                }
            }

            string mangledName = GetCppTypeName(t);

            int nesting = 0;
            int current = 0;
            // Create Namespaces. If a mangledName starts with just :: we will simply ignore it.
            sb.AppendLine();
            for (;;)
            {
                int sep = mangledName.IndexOf("::", current);
                if (sep < 0)
                    break;

                if (sep != 0)
                {
                    // Case of a name not starting with ::
                    sb.Append("namespace " + mangledName.Substring(current, sep - current) + " { ");
                    nesting++;
                }
                current = sep + 2;

            }

            if (full)
            {
                sb.Append("class " + mangledName.Substring(current));
                if (!t.IsValueType)
                {
                    if (t.BaseType != null)
                    {
                        sb.Append(" : public " + GetCppTypeName(t.BaseType));
                    }
                }
                sb.Append(" {");
                sb.AppendLine();
                sb.Append("public:");
                sb.Indent();

                // TODO: Enable once the dependencies are tracked for arrays
                // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked)
                if (!t.IsPointer && !t.IsByRef)
                {
                    sb.AppendLine();
                    sb.Append("static MethodTable * __getMethodTable();");
                }

                IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(t).Slots;
                
                int baseSlots = 0;
                var baseType = t.BaseType;
                while (baseType != null)
                {
                    IReadOnlyList<MethodDesc> baseVirtualSlots = _compilation.NodeFactory.VTable(baseType).Slots;
                    if (baseVirtualSlots != null)
                        baseSlots += baseVirtualSlots.Count;
                    baseType = baseType.BaseType;
                }

                for (int slot = 0; slot < virtualSlots.Count; slot++)
                {
                    MethodDesc virtualMethod = virtualSlots[slot];
                    sb.AppendLine();
                    sb.Append(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot));
                }

                if (t.IsDelegate)
                {
                    sb.AppendLine();
                    sb.Append(GetCodeForDelegate(t));
                }

                OutputTypeFields(sb, t);

                if (t.HasStaticConstructor)
                {
                    _statics.AppendLine();
                    _statics.Append("bool __cctor_" + GetCppTypeName(t).Replace("::", "__") + ";");
                }

                List<MethodDesc> methodList;
                if (_methodLists.TryGetValue(t, out methodList))
                {
                    foreach (var m in methodList)
                    {
                        OutputMethod(sb, m);
                    }
                }
                sb.Exdent();
                sb.AppendLine();
                sb.Append("};");
            }
            else
            {
                sb.Append("class " + mangledName.Substring(current) + ";");
            }

            while (nesting > 0)
            {
                sb.Append("};");
                nesting--;
            }

            // Make some rooms between two type definitions
            if (full)
                sb.AppendEmptyLine();
        }
Example #3
0
        private void OutputMainMethodStub(MethodDesc entrypoint)
        {
            var sb = new CppGenerationBuffer();

            sb.AppendLine();
            if (_compilation.TypeSystemContext.Target.OperatingSystem == TargetOS.Windows)
            {
                sb.Append("int wmain(int argc, wchar_t * argv[]) { ");
            }
            else
            {
                sb.Append("int main(int argc, char * argv[]) {");
            }
            sb.Indent();

            sb.AppendLine();
            sb.Append("if (__initialize_runtime() != 0)");
            sb.Indent();
            sb.AppendLine();
            sb.Append("return -1;");
            sb.Exdent();
            sb.AppendEmptyLine();
            sb.AppendLine();
            sb.Append("ReversePInvokeFrame frame;");
            sb.AppendLine();
            sb.Append("__reverse_pinvoke(&frame);");

            sb.AppendEmptyLine();
            sb.AppendLine();
            sb.Append("::System_Private_CoreLib::Internal::Runtime::CompilerHelpers::StartupCodeHelpers::InitializeModules((intptr_t)RtRHeaderWrapper(), 2);");
            sb.AppendLine();
            sb.Append("int ret = ");
            sb.Append(GetCppMethodDeclarationName(entrypoint.OwningType, GetCppMethodName(entrypoint)));
            sb.Append("(argc, (intptr_t)argv);");

            sb.AppendEmptyLine();
            sb.AppendLine();
            sb.Append("__reverse_pinvoke_return(&frame);");
            sb.AppendLine();
            sb.Append("__shutdown_runtime();");

            sb.AppendLine();
            sb.Append("return ret;");
            sb.Exdent();
            sb.AppendLine();
            sb.Append("}");

            Out.Write(sb.ToString());
        }
Example #4
0
        public void OutputCode(IEnumerable<DependencyNode> nodes, MethodDesc entrypoint)
        {
            BuildMethodLists(nodes);

            ExpandTypes();

            Out.WriteLine("#include \"common.h\"");
            Out.WriteLine("#include \"CppCodeGen.h\"");
            Out.WriteLine();

            Out.Write("/* Forward type definitions */");
            OutputTypes(false);
            Out.WriteLine();
            Out.WriteLine();
            Out.Write("/* Type definitions  */");
            OutputTypes(true);

            var sb = new CppGenerationBuffer();

            foreach (var externC in _externCSignatureMap)
            {
                string importName = externC.Key;
                // TODO: hacky special-case
                if (importName != "memmove" && importName != "malloc") // some methods are already declared by the CRT headers
                {
                    sb.AppendLine();
                    sb.Append(GetCppMethodDeclaration(null, false, importName, externC.Value));
                }
            }
            Out.Write(sb.ToString());
            sb.Clear();

            foreach (var t in _cppSignatureNames.Keys)
            {
                // TODO: Enable once the dependencies are tracked for arrays
                // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked)
                if (!t.IsPointer && !t.IsByRef)
                {
                    sb.AppendLine();
                    sb.Append(GetCodeForType(t));
                }

                List<MethodDesc> methodList;
                if (_methodLists.TryGetValue(t, out methodList))
                {
                    foreach (var m in methodList)
                    {
                        var methodCodeNode = (CppMethodCodeNode)_compilation.NodeFactory.MethodEntrypoint(m);
                        sb.AppendLine();
                        sb.Append(methodCodeNode.CppCode);

                        var alternateName = _compilation.NodeFactory.GetSymbolAlternateName(methodCodeNode);
                        if (alternateName != null)
                        {
                            sb.AppendLine();
                            sb.Append(GetCppMethodDeclaration(m, true, alternateName));
                            sb.AppendLine();
                            sb.Append("{");
                            sb.Indent();
                            sb.AppendLine();
                            if (!m.Signature.ReturnType.IsVoid)
                            {
                                sb.Append("return ");
                            }
                            sb.Append(GetCppMethodDeclarationName(m.OwningType, GetCppMethodName(m)));
                            sb.Append("(");
                            sb.Append(GetCppMethodCallParamList(m));
                            sb.Append(");");
                            sb.Exdent();
                            sb.AppendLine();
                            sb.Append("}");
                        }
                    }
                }
            }
            Out.Write(sb.ToString());
            sb.Clear();

            if (entrypoint != null)
            {
                // Stub for main method
                sb.AppendLine();
                if (_compilation.TypeSystemContext.Target.OperatingSystem == TargetOS.Windows)
                {
                    sb.Append("int wmain(int argc, wchar_t * argv[]) { ");
                }
                else
                {
                    sb.Append("int main(int argc, char * argv[]) {");
                }
                sb.Indent();

                sb.AppendLine();
                sb.Append("if (__initialize_runtime() != 0)");
                sb.Indent();
                sb.AppendLine();
                sb.Append("return -1;");
                sb.Exdent();
                sb.AppendEmptyLine();
                sb.AppendLine();
                sb.Append("ReversePInvokeFrame frame;");
                sb.AppendLine();
                sb.Append("__reverse_pinvoke(&frame);");

                sb.AppendEmptyLine();
                sb.AppendLine();
                sb.Append("int ret = ");
                sb.Append(GetCppMethodDeclarationName(entrypoint.OwningType, GetCppMethodName(entrypoint)));
                sb.Append("(argc, (intptr_t)argv);");

                sb.AppendEmptyLine();
                sb.AppendLine();
                sb.Append("__reverse_pinvoke_return(&frame);");
                sb.AppendLine();
                sb.Append("__shutdown_runtime();");
                
                sb.AppendLine();
                sb.Append("return ret;");
                sb.Exdent();
                sb.AppendLine();
                sb.Append("}");
            }

            Out.Write(sb.ToString());
            sb.Clear();
            Out.Dispose();
        }
Example #5
0
        public void OutputCode(IEnumerable<DependencyNode> nodes, MethodDesc entrypoint, NodeFactory factory)
        {
            var sb = new CppGenerationBuffer();
            BuildMethodLists(nodes);

            ExpandTypes();

            Out.WriteLine("#include \"common.h\"");
            Out.WriteLine("#include \"CppCodeGen.h\"");
            Out.WriteLine();


            _statics = new CppGenerationBuffer();
            _statics.Indent();
            _gcStatics = new CppGenerationBuffer();
            _gcStatics.Indent();
            _threadStatics = new CppGenerationBuffer();
            _threadStatics.Indent();
            _gcThreadStatics = new CppGenerationBuffer();
            _gcThreadStatics.Indent();
            var methodImplementations = new CppGenerationBuffer();

            OutputNodes(nodes, entrypoint, factory, sb, methodImplementations);
            Out.Write(sb.ToString());
            sb.Clear();

            Out.Write("struct {");
            Out.Write(_statics.ToString());
            Out.Write("} __statics;");

            Out.Write("struct {");
            Out.Write(_gcStatics.ToString());
            Out.Write("} __gcStatics;");

            Out.Write("struct {");
            Out.Write(_gcStatics.ToString());
            Out.Write("} __gcThreadStatics;");


            foreach (var externC in _externCSignatureMap)
            {
                string importName = externC.Key;
                // TODO: hacky special-case
                if (importName != "memmove" && importName != "malloc") // some methods are already declared by the CRT headers
                {
                    sb.AppendLine();
                    sb.Append(GetCppMethodDeclaration(null, false, importName, externC.Value));
                }
            }
            Out.Write(sb.ToString());
            sb.Clear();

            Out.Write(methodImplementations.ToString());
            methodImplementations.Clear();

            if (entrypoint != null)
            {
                // Stub for main method
                sb.AppendLine();
                if (_compilation.TypeSystemContext.Target.OperatingSystem == TargetOS.Windows)
                {
                    sb.Append("int wmain(int argc, wchar_t * argv[]) { ");
                }
                else
                {
                    sb.Append("int main(int argc, char * argv[]) {");
                }
                sb.Indent();

                sb.AppendLine();
                sb.Append("if (__initialize_runtime() != 0)");
                sb.Indent();
                sb.AppendLine();
                sb.Append("return -1;");
                sb.Exdent();
                sb.AppendEmptyLine();
                sb.AppendLine();
                sb.Append("ReversePInvokeFrame frame;");
                sb.AppendLine();
                sb.Append("__reverse_pinvoke(&frame);");

                sb.AppendEmptyLine();
                sb.AppendLine();
                sb.Append("int ret = ");
                sb.Append(GetCppMethodDeclarationName(entrypoint.OwningType, GetCppMethodName(entrypoint)));
                sb.Append("(argc, (intptr_t)argv);");

                sb.AppendEmptyLine();
                sb.AppendLine();
                sb.Append("__reverse_pinvoke_return(&frame);");
                sb.AppendLine();
                sb.Append("__shutdown_runtime();");

                sb.AppendLine();
                sb.Append("return ret;");
                sb.Exdent();
                sb.AppendLine();
                sb.Append("}");
            }
            Out.Write(sb.ToString());
            sb.Clear();
            Out.Dispose();
        }