diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2018-03-06 11:14:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-06 11:14:16 +0300 |
commit | bce98342633901dc6202f23597598526380af010 (patch) | |
tree | d7a97341b9861d7353daac8dcc8487ca344d691a /src/ILCompiler.CppCodeGen | |
parent | 4b9c387857d9dbc9f1fe0bdb046b57c3a4499be6 (diff) |
Progress towards sealed vtable support in CppCodegen (#5495)
I wanted to get rid of the CppCodegen special casing around sealed vtables that was added last week; this became kind of tricky and I ran out of time I allocated myself for it. It seems like interface dispatch is kind of broken in general for CppCodeGen.
This has a couple changes towards the goal:
* Add TargetArchitecture.Cpp64 for CppCodegen so that we can distinguish it from x64
* This forced me to fix the misuse of x64 assembly unboxing helpers because there's no CPU emitter for Cpp64.
* Remove duplication of vtable slot calculation. The logic is different when sealed virtuals are in play. We should just use the common helper.
* Devirtualize calls to final methods. These could be in the sealed vtable which makes the dispatch tricky; just don't use the vtable.
Diffstat (limited to 'src/ILCompiler.CppCodeGen')
5 files changed, 84 insertions, 24 deletions
diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs index baf0339aa..d282e1f27 100644 --- a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs +++ b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs @@ -40,8 +40,7 @@ namespace ILCompiler.DependencyAnalysis protected override IMethodNode CreateUnboxingStubNode(MethodDesc method) { - // TODO: this is wrong: this returns an assembly stub node - return new UnboxingStubNode(method, Target); + return new CppUnboxingStubNode(method); } protected override ISymbolNode CreateReadyToRunHelperNode(ReadyToRunHelperKey helperCall) diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppUnboxingStubNode.cs b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppUnboxingStubNode.cs new file mode 100644 index 000000000..916c94d9e --- /dev/null +++ b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppUnboxingStubNode.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Diagnostics; + +using ILCompiler.DependencyAnalysisFramework; + +using Internal.Text; +using Internal.TypeSystem; + +namespace ILCompiler.DependencyAnalysis +{ + internal class CppUnboxingStubNode : DependencyNodeCore<NodeFactory>, IMethodNode + { + public CppUnboxingStubNode(MethodDesc method) + { + Debug.Assert(method.OwningType.IsValueType && !method.Signature.IsStatic); + Method = method; + } + + public MethodDesc Method { get; } + + public int ClassCode => 17864523; + + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + { + sb.Append("unbox_").Append(nameMangler.GetMangledMethodName(Method)); + } + + public int CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return comparer.Compare(this.Method, ((CppUnboxingStubNode)other).Method); + } + + public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) + { + return new DependencyListEntry[] { + new DependencyListEntry(factory.MethodEntrypoint(Method), "Target of unboxing") }; + } + + protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + + public static string GetMangledName(NameMangler nameMangler, MethodDesc method) + { + return "unbox_" + nameMangler.GetMangledMethodName(method); + } + + public override bool StaticDependenciesAreComputed => true; + public override bool HasDynamicDependencies => false; + public override bool InterestingForDynamicDependencyAnalysis => false; + public override bool HasConditionalStaticDependencies => false; + + public int Offset => throw new System.NotImplementedException(); + + public bool RepresentsIndirectionCell => throw new System.NotImplementedException(); + + public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) + { + return null; + } + public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) + { + return null; + } + } +} diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs index ef08550b7..fb2130704 100644 --- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs +++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs @@ -894,12 +894,12 @@ namespace ILCompiler.CppCodeGen { relocCode.Append("dispatchMapModule"); } - else if(reloc.Target is UnboxingStubNode) + else if(reloc.Target is CppUnboxingStubNode) { - var method = reloc.Target as UnboxingStubNode; + var method = reloc.Target as CppUnboxingStubNode; relocCode.Append("(void*)&"); - relocCode.Append(GetCppMethodDeclarationName(method.Method.OwningType, UnboxingStubNode.GetMangledName(factory.NameMangler, method.Method), false)); + relocCode.Append(GetCppMethodDeclarationName(method.Method.OwningType, method.GetMangledName(factory.NameMangler), false)); } else { @@ -1202,23 +1202,15 @@ namespace ILCompiler.CppCodeGen if (typeNode is ConstructedEETypeNode) { - IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(nodeType.GetClosestDefType()).Slots; + DefType closestDefType = nodeType.GetClosestDefType(); - 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; - } + IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(closestDefType).Slots; - for (int slot = 0; slot < virtualSlots.Count; slot++) + foreach (MethodDesc slot in virtualSlots) { - MethodDesc virtualMethod = virtualSlots[slot]; typeDefinitions.AppendLine(); - typeDefinitions.Append(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot)); + int slotNumber = VirtualMethodSlotHelper.GetVirtualMethodSlot(_compilation.NodeFactory, slot, closestDefType); + typeDefinitions.Append(GetCodeForVirtualMethod(slot, slotNumber)); } if (nodeType.IsDelegate) @@ -1242,7 +1234,7 @@ namespace ILCompiler.CppCodeGen typeDefinitions.AppendLine(); AppendCppMethodDeclaration(typeDefinitions, m, false); typeDefinitions.AppendLine(); - AppendCppMethodDeclaration(typeDefinitions, m, false, null, null, UnboxingStubNode.GetMangledName(factory.NameMangler, m)); + AppendCppMethodDeclaration(typeDefinitions, m, false, null, null, CppUnboxingStubNode.GetMangledName(factory.NameMangler, m)); } } @@ -1342,13 +1334,13 @@ namespace ILCompiler.CppCodeGen /// </summary> /// <param name="unboxingStubNode">The unboxing stub node to be output</param> /// <param name="methodImplementations">The buffer in which to write out the C++ code</param> - private void OutputUnboxingStubNode(UnboxingStubNode unboxingStubNode) + private void OutputUnboxingStubNode(CppUnboxingStubNode unboxingStubNode) { Out.WriteLine(); CppGenerationBuffer sb = new CppGenerationBuffer(); sb.AppendLine(); - AppendCppMethodDeclaration(sb, unboxingStubNode.Method, true, null, null, UnboxingStubNode.GetMangledName(_compilation.NameMangler, unboxingStubNode.Method)); + AppendCppMethodDeclaration(sb, unboxingStubNode.Method, true, null, null, unboxingStubNode.GetMangledName(_compilation.NameMangler)); sb.AppendLine(); sb.Append("{"); sb.Indent(); @@ -1405,8 +1397,8 @@ namespace ILCompiler.CppCodeGen { if (node is CppMethodCodeNode) OutputMethodNode(node as CppMethodCodeNode); - else if (node is UnboxingStubNode) - OutputUnboxingStubNode(node as UnboxingStubNode); + else if (node is CppUnboxingStubNode) + OutputUnboxingStubNode(node as CppUnboxingStubNode); } Out.Dispose(); diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs index ae062dad6..560820ad2 100644 --- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs +++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs @@ -1151,7 +1151,7 @@ namespace Internal.IL { // TODO: Null checks - if (method.IsVirtual) + if (method.IsVirtual && !method.IsFinal && !method.OwningType.IsSealed()) { // TODO: Full resolution of virtual methods if (!method.IsNewSlot) diff --git a/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj b/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj index 1ef83f8bd..80a2a51f2 100644 --- a/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj +++ b/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj @@ -32,6 +32,7 @@ <Compile Include="Compiler\CppNodeMangler.cs" /> <Compile Include="Compiler\CppCodegenCompilation.cs" /> <Compile Include="Compiler\CppCodegenCompilationBuilder.cs" /> + <Compile Include="Compiler\DependencyAnalysis\CppUnboxingStubNode.cs" /> <Compile Include="CppCodeGen\DependencyNodeIterator.cs" /> <Compile Include="CppCodeGen\EvaluationStack.cs" /> <Compile Include="CppCodeGen\CppGenerationBuffer.cs" /> |