Example #1
0
        private void OutputTypes(bool full)
        {
            var sb = new CppGenerationBuffer();
            if (full)
            {
                _statics = new CppGenerationBuffer();
                _statics.Indent();
                _gcStatics = new CppGenerationBuffer();
                _gcStatics.Indent();
                _threadStatics = new CppGenerationBuffer();
                _threadStatics.Indent();
                _gcThreadStatics = new CppGenerationBuffer();
                _gcThreadStatics.Indent();
            }

            _emittedTypes = new HashSet<TypeDesc>();
            foreach (var t in _cppSignatureNames.Keys)
            {
                if (t.IsByRef || t.IsPointer)
                    continue;

                // Base class types and valuetype instantance field types may be emitted out-of-order to make them 
                // appear before they are used.
                if (_emittedTypes.Contains(t))
                    continue;

                OutputType(sb, t, full);
            }
            _emittedTypes = null;

            if (full)
            {
                sb.AppendLine();
                sb.Append("struct {");
                // No need to indent or add a new line as _statics is already properly indented
                sb.Append(_statics.ToString());
                sb.AppendLine();
                sb.Append("} __statics;");

                // TODO: Register GC statics with GC
                sb.AppendLine();
                sb.Append("struct {");
                // No need to indent or add a new line as _gcStatics is already properly indented
                sb.Append(_gcStatics.ToString());
                sb.AppendLine();
                sb.Append("} __gcStatics;");

                sb.AppendLine();

                _statics = null;
                _gcStatics = null;
                _threadStatics = null;
                _gcThreadStatics = null;
            }

            Out.Write(sb.ToString());
            sb.Clear();
        }
Example #2
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 #3
0
        /// <summary>
        /// Output C++ code via a given dependency graph
        /// </summary>
        /// <param name="nodes">A set of dependency nodes</param>
        /// <param name="entrypoint">Code entrypoint</param>
        /// <param name="factory">Associated NodeFactory instance</param>
        /// <param name="definitions">Text buffer in which the type and method definitions will be written</param>
        /// <param name="implementation">Text buffer in which the method implementations will be written</param>
        public void OutputNodes(IEnumerable<DependencyNode> nodes, MethodDesc entrypoint, NodeFactory factory, CppGenerationBuffer definitions, CppGenerationBuffer implementation)
        {
            CppGenerationBuffer forwardDefinitions = new CppGenerationBuffer();
            CppGenerationBuffer typeDefinitions = new CppGenerationBuffer();
            CppGenerationBuffer methodTables = new CppGenerationBuffer();
            CppGenerationBuffer optionalFields = new CppGenerationBuffer();
            DependencyNodeIterator nodeIterator = new DependencyNodeIterator(nodes);
            // Output well-known types to avoid build errors

            if (_wellKnownTypeNodes != null)
            {
                foreach (var wellKnownTypeNode in _wellKnownTypeNodes)
                {
                    OutputTypeNode(wellKnownTypeNode, factory, forwardDefinitions, typeDefinitions, methodTables);
                }
            }
            // Iterate through nodes
            foreach (var node in nodeIterator.GetNodes())
            {
                if (node is EETypeNode && !_emittedTypes.Contains(((EETypeNode)node).Type))
                    OutputTypeNode(node as EETypeNode, factory, forwardDefinitions, typeDefinitions, methodTables);

                else if (node is CppMethodCodeNode)
                    OutputMethodNode(node as CppMethodCodeNode, implementation);

                else if (node is EETypeOptionalFieldsNode)
                    optionalFields.Append(GetCodeForObjectNode(node as EETypeOptionalFieldsNode, factory));
            }

            definitions.Append(forwardDefinitions.ToString());
            forwardDefinitions.Clear();
            definitions.Append(typeDefinitions.ToString());
            typeDefinitions.Clear();
            definitions.Append(methodTables.ToString());
            methodTables.Clear();
            definitions.Append(optionalFields.ToString());
            optionalFields.Clear();
        }
Example #4
0
        private void OutputTypes(bool full)
        {
            var sb = new CppGenerationBuffer();
            if (full)
            {
                _statics = new CppGenerationBuffer();
                _statics.Indent();
                _gcStatics = new CppGenerationBuffer();
                _gcStatics.Indent();
                _threadStatics = new CppGenerationBuffer();
                _threadStatics.Indent();
                _gcThreadStatics = new CppGenerationBuffer();
                _gcThreadStatics.Indent();
            }

            _emittedTypes = new HashSet<TypeDesc>();
            foreach (var t in _cppSignatureNames.Keys)
            {
                if (t.IsByRef || t.IsPointer)
                    continue;

                // Base class types and valuetype instantance field types may be emitted out-of-order to make them 
                // appear before they are used.
                if (_emittedTypes.Contains(t))
                    continue;

                OutputType(sb, t, full);
            }
            _emittedTypes = null;

            if (full)
            {
                sb.AppendLine();
                sb.Append("struct {");
                // No need to indent or add a new line as _statics is already properly indented
                sb.Append(_statics.ToString());
                sb.AppendLine();
                sb.Append("} __statics;");

                // TODO: Register GC statics with GC
                sb.AppendLine();
                sb.Append("struct {");
                // No need to indent or add a new line as _gcStatics is already properly indented
                sb.Append(_gcStatics.ToString());
                sb.AppendLine();
                sb.Append("} __gcStatics;");

                sb.AppendLine();
                // @TODO_SDM: do for real - note: the 'extra' series are just testing the init syntax for 0-length arrays, they should be removed
                // TODO: preinitialized 0-length arrays are not supported in CLang
                sb.Append("#ifdef _MSC_VER");
                sb.AppendLine();
                sb.Append("StaticGcDesc __gcStaticsDescs = { 1, { { sizeof(__gcStatics), 0 }, { 123, 456 }, { 789, 101112 } } };");
                sb.AppendLine();
                sb.Append("#else");
                sb.AppendLine();
                sb.Append("StaticGcDesc __gcStaticsDescs;");
                sb.AppendLine();
                sb.Append("#endif");

                sb.AppendLine();
                sb.Append("SimpleModuleHeader __module = { &__gcStatics, &__gcStaticsDescs };");


                _statics = null;
                _gcStatics = null;
                _threadStatics = null;
                _gcThreadStatics = null;
            }

            Out.Write(sb.ToString());
            sb.Clear();
        }
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();
        }