Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2017-07-30 19:28:40 +0300
committerJan Kotas <jkotas@microsoft.com>2017-07-30 20:13:07 +0300
commit5b618edad65e28956c70cd0566c73644639f92cf (patch)
treec4744d6ba14b2d749bf50a01a456ed4ab30b4711 /src/ILCompiler.CppCodeGen
parent7e5a64bb3c7c05e61954b04267aa234b57983435 (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.cs96
-rw-r--r--src/ILCompiler.CppCodeGen/src/CppCodeGen/DependencyNodeIterator.cs31
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
+}