diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2018-03-09 01:04:01 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2018-03-09 01:04:01 +0300 |
commit | 2044e37b95eac1851361336bb366774b4b3c86d5 (patch) | |
tree | 9d789074494a594be21072277d1344ecbeb701db | |
parent | 05387754f374ab9fc68eae7123a9b18c5bafd73c (diff) |
Fix up some alignments (#5517)
* Fix up some alignments
* Optional fields is a bunch of bytes without relocs. We don't need a pointer alignment.
* Sealed vtables are a bunch of 32bit relative relocs. They are not pointer sized.
* R2R helpers don't have addresses that are visible from managed code. We don't need to align them at 4 byte boundaries.
Saves around 10 kB on the size of a Hello world. Won't make a huge difference, but this was an easy thing.
* Fix ARM64 code alignment
6 files changed, 43 insertions, 7 deletions
diff --git a/src/Common/src/TypeSystem/Common/TargetDetails.cs b/src/Common/src/TypeSystem/Common/TargetDetails.cs index a17a5157a..b7fc058bf 100644 --- a/src/Common/src/TypeSystem/Common/TargetDetails.cs +++ b/src/Common/src/TypeSystem/Common/TargetDetails.cs @@ -130,17 +130,36 @@ namespace Internal.TypeSystem } /// <summary> - /// Gets the minimum required method alignment. + /// Gets the minimum required alignment for methods whose address is visible + /// to managed code. /// </summary> public int MinimumFunctionAlignment { get { // We use a minimum alignment of 4 irrespective of the platform. + // This is to prevent confusing the method address with a fat function pointer. return 4; } } + public int MinimumCodeAlignment + { + get + { + switch (Architecture) + { + case TargetArchitecture.ARM: + case TargetArchitecture.ARMEL: + return 2; + case TargetArchitecture.ARM64: + return 4; + default: + return 1; + } + } + } + public TargetDetails(TargetArchitecture architecture, TargetOS targetOS, TargetAbi abi) { Architecture = architecture; diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs index db568a3e8..0bc9db8c6 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs @@ -16,6 +16,12 @@ namespace ILCompiler.DependencyAnalysis { } + /// <summary> + /// Gets a value indicating whether the stub's address is visible from managed code + /// and could be a target of a managed calli. + /// </summary> + protected virtual bool IsVisibleFromManagedCode => true; + public override ObjectNodeSection Section => ObjectNodeSection.TextSection; public override bool StaticDependenciesAreComputed => true; @@ -26,19 +32,26 @@ namespace ILCompiler.DependencyAnalysis public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { + // If the address is expected to be visible from managed code, we need to align + // at the managed code boundaries to prevent the stub from being confused with + // a fat fuction pointer. Otherwise we can align tighter. + int alignment = IsVisibleFromManagedCode ? + factory.Target.MinimumFunctionAlignment : + factory.Target.MinimumCodeAlignment; + switch (factory.Target.Architecture) { case TargetArchitecture.X64: X64.X64Emitter x64Emitter = new X64.X64Emitter(factory, relocsOnly); EmitCode(factory, ref x64Emitter, relocsOnly); - x64Emitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment); + x64Emitter.Builder.RequireInitialAlignment(alignment); x64Emitter.Builder.AddSymbol(this); return x64Emitter.Builder.ToObjectData(); case TargetArchitecture.X86: X86.X86Emitter x86Emitter = new X86.X86Emitter(factory, relocsOnly); EmitCode(factory, ref x86Emitter, relocsOnly); - x86Emitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment); + x86Emitter.Builder.RequireInitialAlignment(alignment); x86Emitter.Builder.AddSymbol(this); return x86Emitter.Builder.ToObjectData(); @@ -46,14 +59,14 @@ namespace ILCompiler.DependencyAnalysis case TargetArchitecture.ARMEL: ARM.ARMEmitter armEmitter = new ARM.ARMEmitter(factory, relocsOnly); EmitCode(factory, ref armEmitter, relocsOnly); - armEmitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment); + armEmitter.Builder.RequireInitialAlignment(alignment); armEmitter.Builder.AddSymbol(this); return armEmitter.Builder.ToObjectData(); case TargetArchitecture.ARM64: ARM64.ARM64Emitter arm64Emitter = new ARM64.ARM64Emitter(factory, relocsOnly); EmitCode(factory, ref arm64Emitter, relocsOnly); - arm64Emitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment); + arm64Emitter.Builder.RequireInitialAlignment(alignment); arm64Emitter.Builder.AddSymbol(this); return arm64Emitter.Builder.ToObjectData(); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs index 0cc9ef205..ba0b4739e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs @@ -51,7 +51,7 @@ namespace ILCompiler.DependencyAnalysis public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); - objData.RequireInitialPointerAlignment(); + objData.RequireInitialAlignment(1); objData.AddSymbol(this); if (!relocsOnly) diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs index ddd1479b2..e7c36429d 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs @@ -63,6 +63,8 @@ namespace ILCompiler.DependencyAnalysis } } + protected override bool IsVisibleFromManagedCode => false; + protected sealed override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); public override bool IsShareable => true; diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs index 7b941ec85..168a14743 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs @@ -90,6 +90,8 @@ namespace ILCompiler.DependencyAnalysis } } + protected override bool IsVisibleFromManagedCode => false; + protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); public ReadyToRunHelperId Id => _id; diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs index 4f7e5ebe3..ec1dca987 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs @@ -128,7 +128,7 @@ namespace ILCompiler.DependencyAnalysis public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); - objData.RequireInitialPointerAlignment(); + objData.RequireInitialAlignment(4); objData.AddSymbol(this); if (BuildSealedVTableSlots(factory, relocsOnly)) |