diff options
author | Jan Kotas <jkotas@microsoft.com> | 2017-07-30 19:28:40 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2017-07-30 20:13:07 +0300 |
commit | 5b618edad65e28956c70cd0566c73644639f92cf (patch) | |
tree | c4744d6ba14b2d749bf50a01a456ed4ab30b4711 /src/ILCompiler.CppCodeGen | |
parent | 7e5a64bb3c7c05e61954b04267aa234b57983435 (diff) |
CppCodeGen: Fix missing forward declarations
Track forward declarations separately from Constructed/Necessary type nodes
Diffstat (limited to 'src/ILCompiler.CppCodeGen')
-rw-r--r-- | src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs | 96 | ||||
-rw-r--r-- | src/ILCompiler.CppCodeGen/src/CppCodeGen/DependencyNodeIterator.cs | 31 |
2 files changed, 101 insertions, 26 deletions
diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs index 5e5069a63..e750045b5 100644 --- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs +++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs @@ -56,6 +56,22 @@ namespace ILCompiler.CppCodeGen BuildExternCSignatureMap(); } + // Mangled type names referenced by the generated code + private Dictionary<TypeDesc, string> _mangledNames = new Dictionary<TypeDesc, string>(); + + private string GetMangledTypeName(TypeDesc type) + { + string mangledName; + if (_mangledNames.TryGetValue(type, out mangledName)) + return mangledName; + + mangledName = _compilation.NameMangler.GetMangledTypeName(type); + + _mangledNames.Add(type, mangledName); + + return mangledName; + } + private Dictionary<TypeDesc, string> _cppSignatureNames = new Dictionary<TypeDesc, string>(); public string GetCppSignatureTypeName(TypeDesc type) @@ -270,7 +286,7 @@ namespace ILCompiler.CppCodeGen case TypeFlags.Pointer: return GetCppSignatureTypeName(((ParameterizedType)type).ParameterType) + "*"; default: - return _compilation.NameMangler.GetMangledTypeName(type).ToString(); + return GetMangledTypeName(type); } } @@ -284,7 +300,7 @@ namespace ILCompiler.CppCodeGen /// <returns>C++ declaration name for <param name="methodName"/>.</returns> public string GetCppMethodDeclarationName(TypeDesc owningType, string methodName, bool isDeclaration = true) { - var s = _compilation.NameMangler.GetMangledTypeName(owningType); + var s = GetMangledTypeName(owningType); if (isDeclaration && s.StartsWith("::")) { // For a Method declaration we do not need the starting :: @@ -958,7 +974,7 @@ namespace ILCompiler.CppCodeGen CppGenerationBuffer typeDefinitions = new CppGenerationBuffer(); CppGenerationBuffer methodTables = new CppGenerationBuffer(); CppGenerationBuffer additionalNodes = new CppGenerationBuffer(); - DependencyNodeIterator nodeIterator = new DependencyNodeIterator(nodes); + DependencyNodeIterator nodeIterator = new DependencyNodeIterator(nodes, factory); // Number of InterfaceDispatchMapNodes needs to be declared explicitly for Ubuntu and OSX int dispatchMapCount = 0; @@ -972,7 +988,7 @@ namespace ILCompiler.CppCodeGen foreach (var node in nodeIterator.GetNodes()) { if (node is EETypeNode) - OutputTypeNode(node as EETypeNode, factory, forwardDefinitions, typeDefinitions, methodTables); + OutputTypeNode(node as EETypeNode, factory, typeDefinitions, methodTables); else if ((node is EETypeOptionalFieldsNode || node is TypeManagerIndirectionNode || node is GenericCompositionNode) && !(node as ObjectNode).ShouldSkipEmittingObjectNode(factory)) additionalNodes.Append(GetCodeForObjectNode(node as ObjectNode, factory)); else if (node is InterfaceDispatchMapNode) @@ -992,7 +1008,7 @@ namespace ILCompiler.CppCodeGen dispatchPointers.AppendLine(); dispatchPointers.Exdent(); - Out.Write(forwardDefinitions.ToString()); + WriteForwardDefinitions(); Out.Write(typeDefinitions.ToString()); @@ -1045,7 +1061,54 @@ namespace ILCompiler.CppCodeGen Out.Write(sb.ToString()); } } - private void OutputTypeNode(IEETypeNode typeNode, NodeFactory factory, CppGenerationBuffer forwardDefinitions, CppGenerationBuffer typeDefinitions, CppGenerationBuffer methodTable) + + /// <summary> + /// Write forward definitions for all mangled type names referenced by the generated C++ code. This set is tracked separately from + /// the types that need EEType because of the type mangled names are often needed to just get the code to compile but type node is not + /// actually required for it. + /// </summary> + private void WriteForwardDefinitions() + { + CppGenerationBuffer forwardDefinitions = new CppGenerationBuffer(); + + string[] mangledNames = _mangledNames.Values.ToArray(); + Array.Sort(mangledNames); + foreach (string mangledName in mangledNames) + { + int nesting = 0; + int current = 0; + + 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) + " { "); + nesting++; + } + current = sep + 2; + } + + forwardDefinitions.Append("class " + mangledName.Substring(current) + ";"); + + while (nesting > 0) + { + forwardDefinitions.Append(" }"); + nesting--; + } + + forwardDefinitions.AppendLine(); + } + + Out.Write(forwardDefinitions.ToString()); + } + + private void OutputTypeNode(IEETypeNode typeNode, NodeFactory factory, CppGenerationBuffer typeDefinitions, CppGenerationBuffer methodTable) { if (_emittedTypes == null) { @@ -1058,12 +1121,11 @@ namespace ILCompiler.CppCodeGen _emittedTypes.Add(nodeType); // Create Namespaces - string mangledName = _compilation.NameMangler.GetMangledTypeName(nodeType); + string mangledName = GetMangledTypeName(nodeType); int nesting = 0; int current = 0; - forwardDefinitions.AppendLine(); for (;;) { int sep = mangledName.IndexOf("::", current); @@ -1074,7 +1136,6 @@ namespace ILCompiler.CppCodeGen 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++; @@ -1082,8 +1143,6 @@ namespace ILCompiler.CppCodeGen current = sep + 2; } - forwardDefinitions.Append("class " + mangledName.Substring(current) + ";"); - // type definition typeDefinitions.Append("class " + mangledName.Substring(current)); if (!nodeType.IsValueType) @@ -1099,16 +1158,19 @@ namespace ILCompiler.CppCodeGen typeDefinitions.Append("public:"); typeDefinitions.Indent(); - // TODO: Enable once the dependencies are tracked for arrays - // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked) + if (typeNode.Marked) { typeDefinitions.AppendLine(); typeDefinitions.Append("static MethodTable * __getMethodTable();"); } - if (typeNode is ConstructedEETypeNode) + + if (nodeType.IsDefType && !nodeType.IsGenericDefinition) { OutputTypeFields(typeDefinitions, nodeType); + } + if (typeNode is ConstructedEETypeNode) + { IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(nodeType.GetClosestDefType()).Slots; int baseSlots = 0; @@ -1160,7 +1222,6 @@ namespace ILCompiler.CppCodeGen while (nesting > 0) { - forwardDefinitions.Append("};"); typeDefinitions.Append("};"); typeDefinitions.Exdent(); nesting--; @@ -1168,7 +1229,10 @@ namespace ILCompiler.CppCodeGen typeDefinitions.AppendEmptyLine(); // declare method table - methodTable.Append(GetCodeForObjectNode(typeNode as ObjectNode, factory)); + if (typeNode.Marked) + { + methodTable.Append(GetCodeForObjectNode(typeNode as ObjectNode, factory)); + } methodTable.AppendEmptyLine(); } diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/DependencyNodeIterator.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/DependencyNodeIterator.cs index 950398295..7b46483e2 100644 --- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/DependencyNodeIterator.cs +++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/DependencyNodeIterator.cs @@ -17,12 +17,14 @@ namespace ILCompiler.Compiler.CppCodeGen private List<DependencyNode> _nodes; private HashSet<DependencyNode> _visited; private Dictionary<TypeDesc, EETypeNode> _typeToNodeMap; + private NodeFactory _factory; - public DependencyNodeIterator(IEnumerable<DependencyNode> nodes) + public DependencyNodeIterator(IEnumerable<DependencyNode> nodes, NodeFactory factory) { _nodes = new List<DependencyNode>(); _typeToNodeMap = new Dictionary<TypeDesc, EETypeNode>(); _visited = new HashSet<DependencyNode>(); + _factory = factory; foreach (var node in nodes) { if (node is EETypeNode) @@ -56,17 +58,26 @@ namespace ILCompiler.Compiler.CppCodeGen AddTypeNode(baseTypeNode); else if (!_nodes.Contains(baseTypeNode)) _nodes.Add(baseTypeNode); } - foreach (var field in node.Type.GetFields()) + if (!node.Type.IsGenericDefinition) { - EETypeNode fieldNode; - _typeToNodeMap.TryGetValue(field.FieldType, out fieldNode); - if (fieldNode != null) + foreach (var field in node.Type.GetFields()) { - if (fieldNode.Type.IsValueType) + EETypeNode fieldNode; + _typeToNodeMap.TryGetValue(field.FieldType, out fieldNode); + if (fieldNode == null) { - if (!fieldNode.Type.IsPrimitive) - AddTypeNode(fieldNode); - else if (!_nodes.Contains(fieldNode)) _nodes.Add(fieldNode); + if (field.FieldType.IsValueType) + AddTypeNode((EETypeNode)_factory.NecessaryTypeSymbol(field.FieldType)); + } + else + { + if (fieldNode.Type.IsValueType) + { + if (!fieldNode.Type.IsPrimitive) + AddTypeNode(fieldNode); + else if (!_nodes.Contains(fieldNode)) + _nodes.Add(fieldNode); + } } } } @@ -78,4 +89,4 @@ namespace ILCompiler.Compiler.CppCodeGen return _nodes; } } -}
\ No newline at end of file +} |