diff options
author | David Wrighton <davidwr@microsoft.com> | 2017-06-13 03:23:48 +0300 |
---|---|---|
committer | David Wrighton <davidwr@microsoft.com> | 2017-06-13 03:23:48 +0300 |
commit | 72f780f9fe1cdafa37e76a378af68d4f378ef004 (patch) | |
tree | 9b2e2531994f96ca1cb0e462c8825d6bda132cac | |
parent | 7af7188d9eba6d062bb43b64717b713699ed7aec (diff) |
Add support for jump stub generation in CoreRT
- Handle both indirect and direct symbol references
- ARM, X86, and X64 architectures
- First need for these is for a stub that has a well known name which jumps to a specific symbol
- We will use these for custom linkage in scenarios involving multiple PE files on Windows
[tfs-changeset: 1661486]
11 files changed, 160 insertions, 5 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs new file mode 100644 index 000000000..6c8c687d9 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs @@ -0,0 +1,32 @@ +// 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; + +using Internal.TypeSystem; + +using Internal.Text; + +namespace ILCompiler.DependencyAnalysis +{ + public abstract partial class JumpStubNode : AssemblyStubNode + { + private ISymbolNode _target; + + public ISymbolNode Target + { + get + { + return _target; + } + } + + public JumpStubNode(ISymbolNode target) + { + _target = target; + } + + protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NamedJumpStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NamedJumpStubNode.cs new file mode 100644 index 000000000..e3d4afaa4 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NamedJumpStubNode.cs @@ -0,0 +1,23 @@ +// 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 Internal.Text; + +namespace ILCompiler.DependencyAnalysis +{ + class NamedJumpStubNode : JumpStubNode + { + Utf8String _name; + + public NamedJumpStubNode(string name, ISymbolNode target) : base(target) + { + _name = new Utf8String(name); + } + + public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + { + sb.Append(_name); + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs index 1f1b76c3c..2fce7836c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs @@ -401,7 +401,12 @@ namespace ILCompiler.DependencyAnalysis Debug.Assert(TypeSystemContext.HasEagerStaticConstructor((MetadataType)method.OwningType)); return EagerCctorTable.NewNode(MethodEntrypoint(method)); }); - + + _namedJumpStubNodes = new NodeCache<Tuple<string, ISymbolNode>, NamedJumpStubNode>((Tuple<string, ISymbolNode> id) => + { + return new NamedJumpStubNode(id.Item1, id.Item2); + }); + _vTableNodes = new NodeCache<TypeDesc, VTableSliceNode>((TypeDesc type ) => { if (CompilationModuleGroup.ShouldProduceFullVTable(type)) @@ -934,6 +939,13 @@ namespace ILCompiler.DependencyAnalysis return ReadOnlyDataBlob(symbolName, stringBytes, 1); } + private NodeCache<Tuple<string, ISymbolNode>, NamedJumpStubNode> _namedJumpStubNodes; + + public ISymbolNode NamedJumpStub(string name, ISymbolNode target) + { + return _namedJumpStubNodes.GetOrAdd(new Tuple<string, ISymbolNode>(name, target)); + } + /// <summary> /// Returns alternative symbol name that object writer should produce for given symbols /// in addition to the regular one. diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs index df063a9f8..38dd2edd7 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs @@ -52,11 +52,18 @@ namespace ILCompiler.DependencyAnalysis.ARM // b symbol public void EmitJMP(ISymbolNode symbol) { + Debug.Assert(!symbol.RepresentsIndirectionCell); Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_THUMB_BRANCH24); Builder.EmitByte(0); Builder.EmitByte(0xF0); Builder.EmitByte(0); Builder.EmitByte(0xB8); } + + // bx reg + public void EmitJMP(Register destination) + { + Builder.EmitShort((short)(0x47 | ((byte)destination << 3))); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMJumpStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMJumpStubNode.cs new file mode 100644 index 000000000..afbc1a662 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMJumpStubNode.cs @@ -0,0 +1,24 @@ +// 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 ILCompiler.DependencyAnalysis.ARM; + +namespace ILCompiler.DependencyAnalysis +{ + public partial class JumpStubNode + { + protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bool relocsOnly) + { + if (!_target.RepresentsIndirectionCell) + { + encoder.EmitJMP(_target); // b methodEntryPoint + } + else + { + encoder.EmitMOV(encoder.TargetRegister.InterproceduralScratch, _target); + encoder.EmitJMP(encoder.TargetRegister.InterproceduralScratch); + } + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/TargetRegisterMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/TargetRegisterMap.cs index 5e0fde4fa..6ac115a14 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/TargetRegisterMap.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/TargetRegisterMap.cs @@ -16,12 +16,14 @@ namespace ILCompiler.DependencyAnalysis.ARM public readonly Register Arg0; public readonly Register Arg1; public readonly Register Result; + public readonly Register InterproceduralScratch; public TargetRegisterMap(TargetOS os) { Arg0 = Register.R0; Arg1 = Register.R1; Result = Register.R0; + InterproceduralScratch = Register.R12; } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs index 3ca448c3f..76c7aa37f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs @@ -74,8 +74,17 @@ namespace ILCompiler.DependencyAnalysis.X64 public void EmitJMP(ISymbolNode symbol) { - Builder.EmitByte(0xE9); - Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + if (symbol.RepresentsIndirectionCell) + { + Builder.EmitByte(0xff); + Builder.EmitByte(0x25); + Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + } + else + { + Builder.EmitByte(0xE9); + Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + } } public void EmitINT3() diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64JumpStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64JumpStubNode.cs new file mode 100644 index 000000000..ceaa37150 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64JumpStubNode.cs @@ -0,0 +1,16 @@ +// 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 ILCompiler.DependencyAnalysis.X64; + +namespace ILCompiler.DependencyAnalysis +{ + public partial class JumpStubNode + { + protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bool relocsOnly) + { + encoder.EmitJMP(_target); + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X86/X86Emitter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X86/X86Emitter.cs index 72068ff22..b44300b21 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X86/X86Emitter.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X86/X86Emitter.cs @@ -28,8 +28,17 @@ namespace ILCompiler.DependencyAnalysis.X86 public void EmitJMP(ISymbolNode symbol) { - Builder.EmitByte(0xE9); - Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + if (symbol.RepresentsIndirectionCell) + { + Builder.EmitByte(0xff); + Builder.EmitByte(0x25); + Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + } + else + { + Builder.EmitByte(0xE9); + Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + } } private bool InSignedByteRange(int i) diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X86/X86JumpStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X86/X86JumpStubNode.cs new file mode 100644 index 000000000..b95bd1a54 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X86/X86JumpStubNode.cs @@ -0,0 +1,16 @@ +// 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 ILCompiler.DependencyAnalysis.X86; + +namespace ILCompiler.DependencyAnalysis +{ + public partial class JumpStubNode + { + protected override void EmitCode(NodeFactory factory, ref X86Emitter encoder, bool relocsOnly) + { + encoder.EmitJMP(_target); + } + } +} diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index 475866398..25de949da 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -234,6 +234,8 @@ <Compile Include="Compiler\DependencyAnalysis\INodeWithDebugInfo.cs" /> <Compile Include="Compiler\DependencyAnalysis\IExportableSymbolNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\ISymbolNode.cs" /> + <Compile Include="Compiler\DependencyAnalysis\JumpStubNode.cs" /> + <Compile Include="Compiler\DependencyAnalysis\NamedJumpStubNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\NodeFactory.cs" /> <Compile Include="Compiler\DependencyAnalysis\NodeFactory.GenericLookups.cs" /> <Compile Include="Compiler\DependencyAnalysis\NodeFactory.NativeLayout.cs" /> @@ -258,6 +260,7 @@ <Compile Include="Compiler\DependencyAnalysis\VirtualMethodUseNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X64\Register.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X64\X64Emitter.cs" /> + <Compile Include="Compiler\DependencyAnalysis\Target_X64\X64JumpStubNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X64\X64ReadyToRunHelperNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\InterfaceDispatchMapNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X86\AddrMode.cs" /> @@ -265,12 +268,14 @@ <Compile Include="Compiler\DependencyAnalysis\Target_X86\X86UnboxingStubNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X86\Register.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X86\X86Emitter.cs" /> + <Compile Include="Compiler\DependencyAnalysis\Target_X86\X86JumpStubNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X86\X86ReadyToRunHelperNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_X86\X86ReadyToRunGenericHelperNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_ARM\TargetRegisterMap.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_ARM\ARMUnboxingStubNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_ARM\Register.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_ARM\ARMEmitter.cs" /> + <Compile Include="Compiler\DependencyAnalysis\Target_ARM\ARMJumpStubNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_ARM\ARMReadyToRunHelperNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\Target_ARM\ARMReadyToRunGenericHelperNode.cs" /> <Compile Include="Compiler\ExportedMethodsRootProvider.cs" /> |