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(); }
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(); }
/// <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(); }
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(); }
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(); }