diff --git a/Demos/Windows/Run-Mosa.BareMetal.HelloWorld.x86.bat b/Demos/Windows/TODO-Run-Mosa.BareMetal.HelloWorld.x86.bat similarity index 100% rename from Demos/Windows/Run-Mosa.BareMetal.HelloWorld.x86.bat rename to Demos/Windows/TODO-Run-Mosa.BareMetal.HelloWorld.x86.bat diff --git a/Source/Mosa.Compiler.Framework/BaseCodeTransformationStage.cs b/Source/Mosa.Compiler.Framework/BaseCodeTransformationStage.cs index 0a057442e0..803fba0076 100644 --- a/Source/Mosa.Compiler.Framework/BaseCodeTransformationStage.cs +++ b/Source/Mosa.Compiler.Framework/BaseCodeTransformationStage.cs @@ -35,11 +35,9 @@ protected override void Run() { for (var node = BasicBlocks[index].AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { - if (node.IsEmpty) + if (node.IsEmptyOrNop) continue; - //instructionCount++; - if (node.Instruction.ID == 0) continue; // no mapping @@ -49,13 +47,17 @@ protected override void Run() { context.Node = node; visitationContext(context); + continue; } - if (node.IsEmpty) + if (node.IsEmptyOrNop) continue; visitationNodes[node.Instruction.ID]?.Invoke(node); } + + if (MethodCompiler.IsStopped) + return; } } diff --git a/Source/Mosa.Compiler.Framework/BaseMethodCompilerStage.cs b/Source/Mosa.Compiler.Framework/BaseMethodCompilerStage.cs index 3693c119a2..06910ade06 100644 --- a/Source/Mosa.Compiler.Framework/BaseMethodCompilerStage.cs +++ b/Source/Mosa.Compiler.Framework/BaseMethodCompilerStage.cs @@ -178,7 +178,7 @@ public abstract class BaseMethodCompilerStage : ITraceFactory /// /// true if this instance has protected regions; otherwise, false. /// - protected bool HasProtectedRegions { get { return MethodCompiler.Method.ExceptionHandlers.Count != 0; } } + protected bool HasProtectedRegions { get { return Method.ExceptionHandlers.Count != 0; } } /// /// Gets a value indicating whether this instance has code. @@ -569,7 +569,7 @@ protected static void UpdatePhiInstructionTargets(List targets, Basi protected MosaExceptionHandler FindImmediateExceptionContext(int label) { - foreach (var handler in MethodCompiler.Method.ExceptionHandlers) + foreach (var handler in Method.ExceptionHandlers) { if (handler.IsLabelWithinTry(label) || handler.IsLabelWithinHandler(label)) { @@ -582,11 +582,11 @@ protected MosaExceptionHandler FindImmediateExceptionContext(int label) protected MosaExceptionHandler FindNextEnclosingFinallyContext(MosaExceptionHandler exceptionContext) { - int index = MethodCompiler.Method.ExceptionHandlers.IndexOf(exceptionContext); + int index = Method.ExceptionHandlers.IndexOf(exceptionContext); - for (int i = index + 1; i < MethodCompiler.Method.ExceptionHandlers.Count; i++) + for (int i = index + 1; i < Method.ExceptionHandlers.Count; i++) { - var entry = MethodCompiler.Method.ExceptionHandlers[i]; + var entry = Method.ExceptionHandlers[i]; if (!entry.IsLabelWithinTry(exceptionContext.TryStart)) return null; @@ -604,7 +604,7 @@ protected MosaExceptionHandler FindFinallyExceptionContext(InstructionNode node) { int label = node.Label; - foreach (var handler in MethodCompiler.Method.ExceptionHandlers) + foreach (var handler in Method.ExceptionHandlers) { if (handler.IsLabelWithinHandler(label)) { @@ -620,7 +620,7 @@ protected bool IsSourceAndTargetWithinSameTryOrException(InstructionNode node) int leaveLabel = node.Label; int targetLabel = node.BranchTargets[0].First.Label; - foreach (var handler in MethodCompiler.Method.ExceptionHandlers) + foreach (var handler in Method.ExceptionHandlers) { bool one = handler.IsLabelWithinTry(leaveLabel); bool two = handler.IsLabelWithinTry(targetLabel); diff --git a/Source/Mosa.Compiler.Framework/CompilerData.cs b/Source/Mosa.Compiler.Framework/CompilerData.cs index 2586e961cd..c8d4fd46a0 100644 --- a/Source/Mosa.Compiler.Framework/CompilerData.cs +++ b/Source/Mosa.Compiler.Framework/CompilerData.cs @@ -59,6 +59,13 @@ public MethodData GetMethodData(MosaMethod method) } } + public bool IsMethodInlined(MosaMethod method) + { + var methodData = GetMethodData(method); + + return methodData.Inlined; + } + #endregion Methods } } diff --git a/Source/Mosa.Compiler.Framework/CompilerStages/MetadataStage.cs b/Source/Mosa.Compiler.Framework/CompilerStages/MetadataStage.cs index 910c0d2943..fc11afe049 100644 --- a/Source/Mosa.Compiler.Framework/CompilerStages/MetadataStage.cs +++ b/Source/Mosa.Compiler.Framework/CompilerStages/MetadataStage.cs @@ -185,8 +185,12 @@ private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTa if (!method.IsConstructor || method.Signature.Parameters.Count != 0 || method.HasOpenGenericParams) continue; - //if (!Compiler.MethodScanner.IsMethodInvoked(method)) - // break; + // TODO: Inline + //if (Compiler.CompilerData.IsMethodInlined(method)) + // continue; + + if (!Compiler.MethodScanner.IsMethodInvoked(method)) + break; Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.MethodDefinition + method.FullName, 0); @@ -243,12 +247,16 @@ private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTa // 15. Pointer to Methods foreach (var method in methodList) { - if ((!(!method.HasImplementation && method.IsAbstract)) && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams) + Debug.Assert((!(!method.HasImplementation && method.IsAbstract)) == (method.HasImplementation || !method.IsAbstract)); + + if ((!(!method.HasImplementation && method.IsAbstract)) + && !method.HasOpenGenericParams + && !method.DeclaringType.HasOpenGenericParams + + //&& !Compiler.CompilerData.IsMethodInlined(method) // TODO: Inline + && Compiler.MethodScanner.IsMethodInvoked(method)) { - if (Compiler.MethodScanner.IsMethodInvoked(method)) - { - Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, method.FullName, 0); - } + Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, GetMethodNameConsiderPlug(method), 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); } @@ -565,11 +573,11 @@ private LinkerSymbol CreateMethodDefinition(MosaMethod method) writer.Write(value, TypeLayout.NativePointerSize); // 5. Pointer to Method - if (method.HasImplementation && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams) + if (method.HasImplementation && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams /*&& !methodData.Inlined*/) // TODO: Inline { if (Compiler.MethodScanner.IsMethodInvoked(method)) { - Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, method.FullName, 0); + Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, GetMethodNameConsiderPlug(method), 0); } } writer.WriteZeroBytes(TypeLayout.NativePointerSize); @@ -895,5 +903,12 @@ private void WriteArgument(EndianAwareBinaryWriter writer, LinkerSymbol symbol, } #endregion Custom Attributes + + private string GetMethodNameConsiderPlug(MosaMethod method) + { + var plugMethod = Compiler.PlugSystem.GetReplacement(method); + + return (plugMethod == null) ? method.FullName : plugMethod.FullName; + } } } diff --git a/Source/Mosa.Compiler.Framework/CompilerStages/MethodTableStage.cs b/Source/Mosa.Compiler.Framework/CompilerStages/MethodTableStage.cs index 88b7ebf6f4..a410f41f0f 100644 --- a/Source/Mosa.Compiler.Framework/CompilerStages/MethodTableStage.cs +++ b/Source/Mosa.Compiler.Framework/CompilerStages/MethodTableStage.cs @@ -56,6 +56,10 @@ protected override void Finalization() if (!Compiler.MethodScanner.IsMethodInvoked(method)) continue; + // Don't emit entry for plug methods + if (Compiler.PlugSystem.GetReplacement(method) != null) + continue; + // 1. Pointer to Method Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); diff --git a/Source/Mosa.Compiler.Framework/CompilerStages/SetupStage.cs b/Source/Mosa.Compiler.Framework/CompilerStages/SetupStage.cs index 657c89dfe3..eca00692c3 100644 --- a/Source/Mosa.Compiler.Framework/CompilerStages/SetupStage.cs +++ b/Source/Mosa.Compiler.Framework/CompilerStages/SetupStage.cs @@ -37,6 +37,7 @@ protected override void Setup() { setupMethod = Compiler.CreateLinkerMethod(SetupStagerName); + Compiler.CompilerData.GetMethodData(setupMethod).DoNotInline = true; MethodScanner.MethodInvoked(setupMethod, setupMethod); Linker.EntryPoint = Linker.GetSymbol(setupMethod.FullName); diff --git a/Source/Mosa.Compiler.Framework/CompilerStages/TypeInitializerStage.cs b/Source/Mosa.Compiler.Framework/CompilerStages/TypeInitializerStage.cs index 295aa75a10..47c089fa2d 100644 --- a/Source/Mosa.Compiler.Framework/CompilerStages/TypeInitializerStage.cs +++ b/Source/Mosa.Compiler.Framework/CompilerStages/TypeInitializerStage.cs @@ -79,6 +79,9 @@ protected override void Setup() Compiler.PlugSystem.CreatePlug(initializeAssemblyMethod, typeInitializerMethod); + Compiler.CompilerData.GetMethodData(initializeAssemblyMethod).DoNotInline = true; + Compiler.CompilerData.GetMethodData(typeInitializerMethod).DoNotInline = true; + MethodScanner.MethodInvoked(initializeAssemblyMethod, initializeAssemblyMethod); MethodScanner.MethodInvoked(typeInitializerMethod, typeInitializerMethod); diff --git a/Source/Mosa.Compiler.Framework/Linker/Elf/ElfLinker.cs b/Source/Mosa.Compiler.Framework/Linker/Elf/ElfLinker.cs index 32290497de..56cb4472fe 100644 --- a/Source/Mosa.Compiler.Framework/Linker/Elf/ElfLinker.cs +++ b/Source/Mosa.Compiler.Framework/Linker/Elf/ElfLinker.cs @@ -444,14 +444,17 @@ private void WriteSymbolSection(Section section, EndianAwareBinaryWriter writer) foreach (var symbol in linker.Symbols) { + if (symbol.SectionKind == SectionKind.Unknown && symbol.LinkRequests.Count == 0) + continue; + Debug.Assert(symbol.SectionKind != SectionKind.Unknown, "symbol.SectionKind != SectionKind.Unknown"); - if (!(symbol.IsExport || linker.EmitAllSymbols)) + if (!(symbol.IsExternalSymbol || linker.EmitAllSymbols)) continue; var symbolEntry = new SymbolEntry() { - Name = AddToStringTable(symbol.ExportName ?? symbol.Name), + Name = AddToStringTable(symbol.ExternalSymbolName ?? symbol.Name), Value = symbol.VirtualAddress, Size = symbol.Size, SymbolBinding = SymbolBinding.Global, @@ -481,7 +484,7 @@ private void CreateRelocationSections() if (symbol.SectionKind != kind) continue; - if (symbol.IsExport) + if (symbol.IsExternalSymbol) continue; foreach (var patch in symbol.LinkRequests) @@ -489,7 +492,7 @@ private void CreateRelocationSections() if (patch.LinkType == LinkType.Size) continue; - if (!patch.ReferenceSymbol.IsExport) + if (!patch.ReferenceSymbol.IsExternalSymbol) continue; if (patch.ReferenceOffset == 0) @@ -571,7 +574,7 @@ private void EmitRelocation(Section section, EndianAwareBinaryWriter writer) foreach (var symbol in linker.Symbols) { - if (symbol.IsExport) + if (symbol.IsExternalSymbol) continue; foreach (var patch in symbol.LinkRequests) @@ -585,7 +588,7 @@ private void EmitRelocation(Section section, EndianAwareBinaryWriter writer) if (patch.LinkType == LinkType.Size) continue; - if (!patch.ReferenceSymbol.IsExport) // FUTURE: include relocations for static symbols, if option selected + if (!patch.ReferenceSymbol.IsExternalSymbol) // FUTURE: include relocations for static symbols, if option selected continue; var relocationEntry = new RelocationEntry() @@ -612,7 +615,7 @@ private void EmitRelocationAddend(Section section, EndianAwareBinaryWriter write //if (symbol.SectionKind != section.SectionKind) // continue; - if (symbol.IsExport) + if (symbol.IsExternalSymbol) continue; foreach (var patch in symbol.LinkRequests) @@ -626,7 +629,7 @@ private void EmitRelocationAddend(Section section, EndianAwareBinaryWriter write if (patch.LinkType == LinkType.Size) continue; - if (!patch.ReferenceSymbol.IsExport) // FUTURE: include relocations for static symbols, if option selected + if (!patch.ReferenceSymbol.IsExternalSymbol) // FUTURE: include relocations for static symbols, if option selected continue; var relocationAddendEntry = new RelocationAddendEntry() diff --git a/Source/Mosa.Compiler.Framework/Linker/LinkerSymbol.cs b/Source/Mosa.Compiler.Framework/Linker/LinkerSymbol.cs index d28992342c..d5106be546 100644 --- a/Source/Mosa.Compiler.Framework/Linker/LinkerSymbol.cs +++ b/Source/Mosa.Compiler.Framework/Linker/LinkerSymbol.cs @@ -13,8 +13,6 @@ public sealed class LinkerSymbol { public string Name { get; } - public string ExportName { get; internal set; } - public SectionKind SectionKind { get; internal set; } public Stream Stream { get; internal set; } @@ -27,12 +25,16 @@ public sealed class LinkerSymbol public bool IsResolved { get { return VirtualAddress != 0; } } - public bool IsExport { get; set; } + public string ExternalSymbolName { get; internal set; } + + public bool IsExternalSymbol { get; set; } public uint SectionOffset { get; internal set; } public ulong VirtualAddress { get; internal set; } + public bool IsReplaced { get; internal set; } + public List LinkRequests { get; } private readonly object _lock = new object(); @@ -43,7 +45,8 @@ internal LinkerSymbol(string name, uint alignment = 0, SectionKind kind = Sectio Alignment = alignment; SectionKind = kind; LinkRequests = new List(); - IsExport = false; + IsExternalSymbol = false; + IsReplaced = false; } public void SetData(MemoryStream stream) @@ -56,6 +59,11 @@ public void SetData(byte[] data) SetData(new MemoryStream(data)); } + public void SetReplacementStatus(bool replaced) + { + IsReplaced = replaced; + } + public void AddPatch(LinkRequest linkRequest) { lock (_lock) diff --git a/Source/Mosa.Compiler.Framework/Linker/MosaLinker.cs b/Source/Mosa.Compiler.Framework/Linker/MosaLinker.cs index b5e0ff1c1b..ebe751ebbd 100644 --- a/Source/Mosa.Compiler.Framework/Linker/MosaLinker.cs +++ b/Source/Mosa.Compiler.Framework/Linker/MosaLinker.cs @@ -145,7 +145,7 @@ public LinkerSymbol DefineSymbol(string name, SectionKind kind, int alignment, i Symbols.Add(symbol); symbolLookup.Add(name, symbol); - symbol.IsExport = false; + symbol.IsExternalSymbol = false; } symbol.Alignment = aligned; @@ -162,26 +162,6 @@ public LinkerSymbol DefineSymbol(string name, SectionKind kind, int alignment, i } } - public LinkerSymbol DefineExternalSymbol(string name, string externalName, SectionKind kind) - { - lock (_lock) - { - if (!symbolLookup.TryGetValue(name, out LinkerSymbol symbol)) - { - symbol = new LinkerSymbol(name, 0, kind); - - Symbols.Add(symbol); - symbolLookup.Add(name, symbol); - } - - symbol.SectionKind = kind; - symbol.IsExport = true; - symbol.ExportName = externalName; - - return symbol; - } - } - public void SetFirst(LinkerSymbol symbol) { Symbols.Remove(symbol); @@ -217,6 +197,9 @@ private void ApplyPatches() { foreach (var symbol in Symbols) { + if (symbol.IsReplaced) + continue; + foreach (var linkRequest in symbol.LinkRequests) { ApplyPatch(linkRequest); @@ -270,13 +253,16 @@ private void ResolveSectionLayout(LinkerSection section, uint fileOffset, ulong foreach (var symbol in Symbols) { + if (symbol.IsReplaced) + continue; + if (symbol.SectionKind != section.SectionKind) continue; if (symbol.IsResolved) continue; - if (symbol.IsExport) + if (symbol.IsExternalSymbol) continue; symbol.SectionOffset = section.Size; @@ -292,6 +278,9 @@ internal void WriteTo(Stream stream, LinkerSection section) { foreach (var symbol in Symbols) { + if (symbol.IsReplaced) + continue; + if (symbol.SectionKind != section.SectionKind) continue; diff --git a/Source/Mosa.Compiler.Framework/MethodCompiler.cs b/Source/Mosa.Compiler.Framework/MethodCompiler.cs index 5fbefc3647..b522f958c7 100644 --- a/Source/Mosa.Compiler.Framework/MethodCompiler.cs +++ b/Source/Mosa.Compiler.Framework/MethodCompiler.cs @@ -48,11 +48,6 @@ public sealed class MethodCompiler /// public MosaMethod Method { get; } - /// - /// Gets the owner type of the method. - /// - public MosaType Type { get; } - /// /// Gets the basic blocks. /// @@ -169,11 +164,6 @@ public sealed class MethodCompiler /// public Operand ConstantZero64 { get; } - /// - /// Gets a value indicating whether this instance is in SSA form. - /// - public bool IsInSSAForm { get; set; } - /// /// Gets or sets a value indicating whether this instance is execute pipeline. /// @@ -194,11 +184,21 @@ public sealed class MethodCompiler /// public bool IsStackFrameRequired { get; set; } + /// + /// Gets or sets a value indicating whether this instance is method inlined. + /// + public bool IsMethodInlined { get; set; } + /// /// Holds flag that will stop method compiler /// public bool IsStopped { get; private set; } + /// + /// Gets the linker symbol. + /// + public LinkerSymbol Symbol { get; private set; } + /// /// Gets the method scanner. /// @@ -221,7 +221,6 @@ public MethodCompiler(Compiler compiler, MosaMethod method, BasicBlocks basicBlo Compiler = compiler; Method = method; - Type = method.DeclaringType; MethodScheduler = compiler.MethodScheduler; Architecture = compiler.Architecture; TypeSystem = compiler.TypeSystem; @@ -246,15 +245,18 @@ public MethodCompiler(Compiler compiler, MosaMethod method, BasicBlocks basicBlo ThreadID = threadID; IsStopped = false; - IsInSSAForm = false; IsExecutePipeline = true; IsCILDecodeRequired = true; IsStackFrameRequired = true; + IsMethodInlined = false; MethodData = compiler.CompilerData.GetMethodData(Method); MethodData.Counters.Reset(); + // Both defines the symbol and also clears the data + Symbol = Linker.DefineSymbol(Method.FullName, SectionKind.Text, 0, 0); + EvaluateParameterOperands(); CalculateMethodParameterSize(); @@ -339,9 +341,9 @@ private void EvaluateParameterOperands() if (Method.HasThis || Method.HasExplicitThis) { - if (Type.IsValueType) + if (Method.DeclaringType.IsValueType) { - var ptr = Type.ToManagedPointer(); + var ptr = Method.DeclaringType.ToManagedPointer(); SetStackParameter(index++, ptr, "this", true, offset); var size = GetReferenceOrTypeSize(ptr, true); @@ -349,9 +351,9 @@ private void EvaluateParameterOperands() } else { - SetStackParameter(index++, Type, "this", true, offset); + SetStackParameter(index++, Method.DeclaringType, "this", true, offset); - var size = GetReferenceOrTypeSize(Type, true); + var size = GetReferenceOrTypeSize(Method.DeclaringType, true); offset += size; } } @@ -386,6 +388,8 @@ public void Compile() ExecutePipeline(); + //Symbol.SetReplacementStatus(MethodData.Inlined); // TOTO + if (Compiler.CompilerOptions.EnableStatistics) { var log = new TraceLog(TraceType.MethodCounters, Method, string.Empty); @@ -414,7 +418,7 @@ private void ExecutePipeline() InstructionLogger.Run(this, stage); - if (IsStopped) + if (IsStopped/* || IsMethodInlined*/) // TOTO break; } @@ -434,7 +438,7 @@ private void ExecutePipeline() for (int i = 0; i < Pipeline.Count; i++) { var pipelineTicks = executionTimes[i]; - var ticks = pipelineTicks - previousTicks; + var ticks = pipelineTicks == 0 ? 0 : pipelineTicks - previousTicks; var percentage = (ticks * 100) / (double)(totalTicks - startTicks); previousTicks = pipelineTicks; @@ -463,21 +467,16 @@ private void PlugMethod() Compiler.MethodScanner.MethodInvoked(plugMethod, Method); IsMethodPlugged = true; - - Debug.Assert(plugMethod != null); - - var plugSymbol = Operand.CreateSymbolFromMethod(plugMethod, TypeSystem); - - var block = BasicBlocks.CreateBlock(BasicBlock.PrologueLabel); - BasicBlocks.AddHeadBlock(block); - - var ctx = new Context(block); - - ctx.AppendInstruction(IRInstruction.Jmp, null, plugSymbol); - IsCILDecodeRequired = false; - IsExecutePipeline = true; + IsExecutePipeline = false; IsStackFrameRequired = false; + + if (Trace.IsTraceable(5)) + { + var traceLog = new TraceLog(TraceType.MethodInstructions, Method, "XX-Plugged Method"); + traceLog?.Log($"Plugged by {plugMethod.FullName}"); + Trace.PostTraceLog(traceLog); + } } private void PatchDelegate() @@ -493,6 +492,13 @@ private void PatchDelegate() IsCILDecodeRequired = false; IsExecutePipeline = true; + + if (Trace.IsTraceable(5)) + { + var traceLog = new TraceLog(TraceType.MethodDebug, Method, "XX-Delegate Patched"); + traceLog?.Log("This delegate method was patched"); + Trace.PostTraceLog(traceLog); + } } private void ExternalMethod() @@ -509,7 +515,15 @@ private void ExternalMethod() if (intrinsic != null) return; - Linker.DefineExternalSymbol(Method.FullName, Method.ExternMethodName, SectionKind.Text); + Symbol.ExternalSymbolName = Method.ExternMethodName; + Symbol.IsExternalSymbol = true; + + if (Trace.IsTraceable(5)) + { + var traceLog = new TraceLog(TraceType.MethodInstructions, Method, "XX-External Method"); + traceLog?.Log($"This method is external linked: {Method.ExternMethodName}"); + Trace.PostTraceLog(traceLog); + } } private void InternalMethod() @@ -520,6 +534,13 @@ private void InternalMethod() IsCILDecodeRequired = false; IsExecutePipeline = false; IsStackFrameRequired = false; + + if (Trace.IsTraceable(5)) + { + var traceLog = new TraceLog(TraceType.MethodInstructions, Method, "XX-External Method"); + traceLog?.Log($"This method is an internal method"); + Trace.PostTraceLog(traceLog); + } } /// diff --git a/Source/Mosa.Compiler.Framework/MethodData.cs b/Source/Mosa.Compiler.Framework/MethodData.cs index 036d1a7cf7..4cbf122d41 100644 --- a/Source/Mosa.Compiler.Framework/MethodData.cs +++ b/Source/Mosa.Compiler.Framework/MethodData.cs @@ -19,8 +19,6 @@ public sealed class MethodData public bool IsCompiled { get; set; } - public bool IsCILDecoded { get; set; } - public bool IsLinkerGenerated { get; set; } public bool HasProtectedRegions { get; set; } diff --git a/Source/Mosa.Compiler.Framework/MethodScheduler.cs b/Source/Mosa.Compiler.Framework/MethodScheduler.cs index 8807adc68d..3cca3bc760 100644 --- a/Source/Mosa.Compiler.Framework/MethodScheduler.cs +++ b/Source/Mosa.Compiler.Framework/MethodScheduler.cs @@ -157,8 +157,10 @@ public int GetTimestamp() } } - public void AddToInlineQueueByCallee(MethodData calleeMethod, int timestamp) + public void AddToInlineQueueByCallee(MethodData calleeMethod) { + var timestamp = GetTimestamp(); + lock (inlineQueue) { foreach (var method in calleeMethod.CalledBy) @@ -179,27 +181,6 @@ public void AddToInlineQueueByCallee(MethodData calleeMethod, int timestamp) } } - public void AddToInlineQueue(MosaMethod method, int timestamp) - { - Debug.Assert(!method.HasOpenGenericParams); - - lock (inlineQueue) - { - if (!inlineQueue.TryGetValue(method, out int existingtimestamp)) - { - inlineQueue.Add(method, timestamp); - } - else - { - if (existingtimestamp < timestamp) - return; - - inlineQueue.Remove(method); - inlineQueue.Add(method, existingtimestamp); - } - } - } - public void FlushInlineQueue() { bool action = false; diff --git a/Source/Mosa.Compiler.Framework/Mosa.Compiler.Framework.csproj b/Source/Mosa.Compiler.Framework/Mosa.Compiler.Framework.csproj index 7227129941..6c67ed9ef4 100644 --- a/Source/Mosa.Compiler.Framework/Mosa.Compiler.Framework.csproj +++ b/Source/Mosa.Compiler.Framework/Mosa.Compiler.Framework.csproj @@ -10,4 +10,7 @@ + + + \ No newline at end of file diff --git a/Source/Mosa.Compiler.Framework/Stages/CILDecodingStage.cs b/Source/Mosa.Compiler.Framework/Stages/CILDecodingStage.cs index c609442741..ef96de5a55 100644 --- a/Source/Mosa.Compiler.Framework/Stages/CILDecodingStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/CILDecodingStage.cs @@ -67,7 +67,7 @@ protected override void Run() counts = new int[CILInstruction.MaxOpCodeValue]; } - MethodCompiler.SetLocalVariables(MethodCompiler.Method.LocalVariables); + MethodCompiler.SetLocalVariables(Method.LocalVariables); // Create the prologue block var prologue = CreateNewBlock(BasicBlock.PrologueLabel); @@ -137,7 +137,7 @@ protected override void Finish() private void DecodeProtectedRegionTargets() { - foreach (var handler in MethodCompiler.Method.ExceptionHandlers) + foreach (var handler in Method.ExceptionHandlers) { if (handler.TryStart != 0) { @@ -166,9 +166,9 @@ private void DecodeInstructionTargets() { bool branched = false; - for (int i = 0; i < MethodCompiler.Method.Code.Count; i++) + for (int i = 0; i < Method.Code.Count; i++) { - instruction = MethodCompiler.Method.Code[i]; + instruction = Method.Code[i]; if (branched) { @@ -197,9 +197,9 @@ private void DecodeInstructions() // Prefix instruction bool prefix = false; - for (int i = 0; i < MethodCompiler.Method.Code.Count; i++) + for (int i = 0; i < Method.Code.Count; i++) { - instruction = MethodCompiler.Method.Code[i]; + instruction = Method.Code[i]; block = BasicBlocks.GetByLabel(instruction.Offset) ?? block; @@ -228,7 +228,7 @@ private void DecodeInstructions() if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch) { - var nextInstruction = MethodCompiler.Method.Code[i + 1]; + var nextInstruction = Method.Code[i + 1]; if (BasicBlocks.GetByLabel(nextInstruction.Offset) != null) { @@ -312,7 +312,7 @@ Operand IInstructionDecoder.ConvertVirtualRegisterToStackLocal(Operand virtualRe index++; } - var local = MethodCompiler.Method.LocalVariables[index]; + var local = Method.LocalVariables[index]; var stackLocal = MethodCompiler.AddStackLocal(local.Type, local.IsPinned); diff --git a/Source/Mosa.Compiler.Framework/Stages/CILOperandAssignmentStage.cs b/Source/Mosa.Compiler.Framework/Stages/CILOperandAssignmentStage.cs index 93035fc2d7..e3952459e6 100644 --- a/Source/Mosa.Compiler.Framework/Stages/CILOperandAssignmentStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/CILOperandAssignmentStage.cs @@ -38,7 +38,7 @@ protected override void Run() if (!MethodCompiler.IsCILDecodeRequired) return; - if (!MethodCompiler.Method.HasImplementation) + if (!Method.HasImplementation) return; //trace = CreateTraceLog(); diff --git a/Source/Mosa.Compiler.Framework/Stages/CILStaticAllocationResolutionStage.cs b/Source/Mosa.Compiler.Framework/Stages/CILStaticAllocationResolutionStage.cs index 7d1f0d08fe..9ff1b0017d 100644 --- a/Source/Mosa.Compiler.Framework/Stages/CILStaticAllocationResolutionStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/CILStaticAllocationResolutionStage.cs @@ -83,14 +83,14 @@ private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNo } // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name. - var symbolName = MethodCompiler.Linker.DefineSymbol(assignmentField.FullName + "<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize); + var symbolName = Linker.DefineSymbol(assignmentField.FullName + "<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize); // Try to get typeDefinitionSymbol if allocatedType isn't a value type string typeDefinitionSymbol = GetTypeDefinition(allocatedType); if (typeDefinitionSymbol != null) { - MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, typeDefinitionSymbol, 0); + Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, typeDefinitionSymbol, 0); } var staticAddress = Operand.CreateSymbol(assignmentField.FieldType, symbolName.Name); diff --git a/Source/Mosa.Compiler.Framework/Stages/CILTransformationStage.cs b/Source/Mosa.Compiler.Framework/Stages/CILTransformationStage.cs index 5fac79b68a..d42682778a 100644 --- a/Source/Mosa.Compiler.Framework/Stages/CILTransformationStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/CILTransformationStage.cs @@ -1082,17 +1082,16 @@ private void Ldstr(InstructionNode node) * be replaced by a proper VM call. */ - var linker = MethodCompiler.Linker; string symbolName = node.Operand1.Name; string stringdata = node.Operand1.StringData; node.SetInstruction(Select(node.Result, IRInstruction.MoveInt32, IRInstruction.MoveInt64), node.Result, node.Operand1); - var symbol = linker.DefineSymbol(symbolName, SectionKind.ROData, NativeAlignment, (NativePointerSize * 2) + 4 + (stringdata.Length * 2)); + var symbol = Linker.DefineSymbol(symbolName, SectionKind.ROData, NativeAlignment, (NativePointerSize * 2) + 4 + (stringdata.Length * 2)); var stream = symbol.Stream; // Type Definition and sync block - linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbol, 0, Metadata.TypeDefinition + "System.String", 0); + Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbol, 0, Metadata.TypeDefinition + "System.String", 0); stream.WriteZeroBytes(NativePointerSize * 2); diff --git a/Source/Mosa.Compiler.Framework/Stages/CallStage.cs b/Source/Mosa.Compiler.Framework/Stages/CallStage.cs index 9033ea798f..71e2393402 100644 --- a/Source/Mosa.Compiler.Framework/Stages/CallStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/CallStage.cs @@ -57,9 +57,6 @@ private void SetReturn64(Context context) if (Is32BitPlatform) { - //var v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4); - //var v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4); - context.SetInstruction(IRInstruction.GetLow64, Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, Architecture.ReturnRegister), operand); context.AppendInstruction(IRInstruction.GetHigh64, Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, Architecture.ReturnHighRegister), operand); } @@ -91,6 +88,19 @@ private void CallStatic(InstructionNode node) Debug.Assert(method != null); + if (MethodCompiler.Compiler.CompilerData.IsMethodInlined(method)) + { + // If above is true, then a race condition occurred between: + // 1) after inline stage of this method, and + // 2) theinline evaluation stage of the target method + // the only best option at this point is to stop compiling this method. + // Note: It should already be scheduled to be re-compiled! + //MethodCompiler.Stop(); + //return; + } + + //Debug.Assert(!MethodCompiler.Compiler.CompilerData.IsMethodInlined(method)); + operands.RemoveAt(0); var context = new Context(node); diff --git a/Source/Mosa.Compiler.Framework/Stages/CodeGenerationStage.cs b/Source/Mosa.Compiler.Framework/Stages/CodeGenerationStage.cs index c8e4a19683..c6d723fdea 100644 --- a/Source/Mosa.Compiler.Framework/Stages/CodeGenerationStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/CodeGenerationStage.cs @@ -12,7 +12,7 @@ namespace Mosa.Compiler.Framework.Stages /// /// Base class for code generation stages. /// - public class CodeGenerationStage : BaseMethodCompilerStage + public sealed class CodeGenerationStage : BaseMethodCompilerStage { private Counter GeneratedInstructionCount = new Counter("CodeGenerationStage.GeneratedInstructions"); private Counter GeneratedBlockCount = new Counter("CodeGenerationStage.GeneratedBlocks"); @@ -22,7 +22,7 @@ public class CodeGenerationStage : BaseMethodCompilerStage /// /// Holds the stream, where code is emitted to. /// - protected MemoryStream codeStream; + private MemoryStream codeStream; //protected Stream codeStream; @@ -30,7 +30,7 @@ public class CodeGenerationStage : BaseMethodCompilerStage #region Properties - public BaseCodeEmitter CodeEmitter { get; protected set; } + private BaseCodeEmitter CodeEmitter; public bool EmitBinary { get; set; } @@ -68,15 +68,10 @@ protected override void Run() if (!EmitBinary) return; - var symbol = MethodCompiler.Linker.DefineSymbol(MethodCompiler.Method.FullName, SectionKind.Text, 0, 0); + var symbol = Linker.DefineSymbol(Method.FullName, SectionKind.Text, 0, 0); codeStream = new MemoryStream(); - //codeStream = symbol.Stream; - - // Retrieve a stream to place the code into - - // HINT: We need seeking to resolve Labels. Debug.Assert(codeStream.CanSeek, "Can't seek codeReader output stream."); Debug.Assert(codeStream.CanWrite, "Can't write to codeReader output stream."); @@ -106,11 +101,11 @@ protected override void Finish() /// /// Called to emit a list of instructions offered by the instruction provider. /// - protected virtual void EmitInstructions() + private void EmitInstructions() { - var trace = CreateTraceLog(); + var trace = CreateTraceLog(9); - MethodCompiler.MethodData.LabelRegions.Clear(); + MethodData.LabelRegions.Clear(); int labelCurrent = BasicBlock.ReservedLabel; int labelStart = 0; @@ -120,7 +115,7 @@ protected virtual void EmitInstructions() for (var node = block.First; !node.IsBlockEndInstruction; node = node.Next) { - if (node.IsEmpty) + if (node.IsEmptyOrNop) continue; if (node.IsBlockStartInstruction) @@ -141,7 +136,7 @@ protected virtual void EmitInstructions() { if (labelCurrent != BasicBlock.ReservedLabel) { - MethodCompiler.MethodData.AddLabelRegion(labelCurrent, labelStart, CodeEmitter.CurrentPosition - labelStart); + MethodData.AddLabelRegion(labelCurrent, labelStart, CodeEmitter.CurrentPosition - labelStart); } labelCurrent = node.Label; @@ -166,16 +161,16 @@ protected virtual void EmitInstructions() GeneratedBlockCount++; } - MethodCompiler.MethodData.AddLabelRegion(labelCurrent, labelStart, CodeEmitter.CurrentPosition - labelStart); + MethodData.AddLabelRegion(labelCurrent, labelStart, CodeEmitter.CurrentPosition - labelStart); } /// /// Begins the generate. /// - protected virtual void BeginGenerate() + private void BeginGenerate() { CodeEmitter = new BaseCodeEmitter(); - CodeEmitter.Initialize(MethodCompiler.Method.FullName, MethodCompiler.Linker, codeStream); + CodeEmitter.Initialize(Method.FullName, Linker, codeStream); MethodCompiler.Labels = CodeEmitter.Labels; } @@ -184,7 +179,7 @@ protected virtual void BeginGenerate() /// Start of code generation for a block. /// /// The started block. - protected virtual void BlockStart(BasicBlock block) + private void BlockStart(BasicBlock block) { CodeEmitter.Label(block.Label); } @@ -193,7 +188,7 @@ protected virtual void BlockStart(BasicBlock block) /// Completion of code generation for a block. /// /// The completed block. - protected virtual void BlockEnd(BasicBlock block) + private void BlockEnd(BasicBlock block) { // TODO: Adjust BaseCodeEmitter interface to mark the end of label sections, rather than create this special label: CodeEmitter.Label(block.Label + 0x0F000000); @@ -202,7 +197,7 @@ protected virtual void BlockEnd(BasicBlock block) /// /// Code generation completed. /// - protected virtual void EndGenerate() + private void EndGenerate() { CodeEmitter.ResolvePatches(); } diff --git a/Source/Mosa.Compiler.Framework/Stages/EnterSSAStage.cs b/Source/Mosa.Compiler.Framework/Stages/EnterSSAStage.cs index 07e85a5f31..4cc5d83bcc 100644 --- a/Source/Mosa.Compiler.Framework/Stages/EnterSSAStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/EnterSSAStage.cs @@ -81,8 +81,6 @@ private void EnterSSA() { EnterSSA(headBlock); } - - MethodCompiler.IsInSSAForm = true; } /// diff --git a/Source/Mosa.Compiler.Framework/Stages/ExceptionPrologueStage.cs b/Source/Mosa.Compiler.Framework/Stages/ExceptionPrologueStage.cs index 04a6e8667c..3b9b471ca0 100644 --- a/Source/Mosa.Compiler.Framework/Stages/ExceptionPrologueStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/ExceptionPrologueStage.cs @@ -27,7 +27,7 @@ protected override void Run() private void InsertExceptionStartInstructions() { - foreach (var clause in MethodCompiler.Method.ExceptionHandlers) + foreach (var clause in Method.ExceptionHandlers) { if (clause.ExceptionHandlerType == ExceptionHandlerType.Exception) { diff --git a/Source/Mosa.Compiler.Framework/Stages/ExceptionStage.cs b/Source/Mosa.Compiler.Framework/Stages/ExceptionStage.cs index 4745abccdb..b756d30cd2 100644 --- a/Source/Mosa.Compiler.Framework/Stages/ExceptionStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/ExceptionStage.cs @@ -68,7 +68,7 @@ protected override void Run() { for (var node = BasicBlocks[i].First; !node.IsBlockEndInstruction; node = node.Next) { - if (node.IsEmpty) + if (node.IsEmptyOrNop) continue; if (dispatches.TryGetValue(node.Instruction, out Dispatch dispatch)) diff --git a/Source/Mosa.Compiler.Framework/Stages/ExitSSAStage.cs b/Source/Mosa.Compiler.Framework/Stages/ExitSSAStage.cs index 43a9fbe3a9..72bbc13389 100644 --- a/Source/Mosa.Compiler.Framework/Stages/ExitSSAStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/ExitSSAStage.cs @@ -43,8 +43,6 @@ protected override void Run() ProcessPhiInstruction(node); } } - - MethodCompiler.IsInSSAForm = false; } /// diff --git a/Source/Mosa.Compiler.Framework/Stages/IRLongDecompositionStage.cs b/Source/Mosa.Compiler.Framework/Stages/IRLongDecompositionStage.cs index 3ca14114ac..ef48254fdc 100644 --- a/Source/Mosa.Compiler.Framework/Stages/IRLongDecompositionStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/IRLongDecompositionStage.cs @@ -245,8 +245,7 @@ private void CompareInt64x32(Context context) return; } - // FUTURE: Use the compiler option instead - if (MethodCompiler.IsInSSAForm) + if (CompilerOptions.EnableSSA) { CompareInteger64x32SSA(context); } diff --git a/Source/Mosa.Compiler.Framework/Stages/InlineEvaluationStage.cs b/Source/Mosa.Compiler.Framework/Stages/InlineEvaluationStage.cs index 9c76d81ba5..8c0b1623f1 100644 --- a/Source/Mosa.Compiler.Framework/Stages/InlineEvaluationStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/InlineEvaluationStage.cs @@ -1,6 +1,7 @@ // Copyright (c) MOSA Project. Licensed under the New BSD License. using Mosa.Compiler.Framework.IR; +using Mosa.Compiler.MosaTypeSystem; using System.Collections.Generic; using System.Diagnostics; @@ -26,29 +27,43 @@ protected override void Initialize() protected override void Run() { - var trace = CreateTraceLog("Inline"); + var trace = CreateTraceLog(); - bool firstCompile = (MethodData.CompileCount == 0); - - var currentInlineStatus = MethodData.Inlined; - - MethodData.IsCompiled = true; + MethodData.IsCompiled = false; + MethodData.BasicBlocks = null; MethodData.HasProtectedRegions = HasProtectedRegions; MethodData.IsLinkerGenerated = Method.IsCompilerGenerated; - MethodData.IsCILDecoded = MethodCompiler.IsCILDecodeRequired || (!Method.IsCompilerGenerated && Method.HasImplementation); - MethodData.HasLoops = false; MethodData.IsMethodImplementationReplaced = MethodCompiler.IsMethodPlugged; - MethodData.HasDoNotInlineAttribute = MethodCompiler.Method.IsNoInlining; - MethodData.HasAggressiveInliningAttribute = MethodCompiler.Method.IsAggressiveInlining; + MethodData.HasDoNotInlineAttribute = Method.IsNoInlining; + MethodData.HasAggressiveInliningAttribute = Method.IsAggressiveInlining; MethodData.HasAddressOfInstruction = false; + MethodData.HasLoops = false; MethodData.IsVirtual = Method.IsVirtual; MethodData.IsDevirtualized = Method.IsVirtual && !TypeLayout.IsMethodOverridden(Method); + trace?.Log($"DoNotInline: {MethodData.DoNotInline}"); + trace?.Log($"IsVirtual: {MethodData.IsVirtual}"); + trace?.Log($"IsDevirtualized: {MethodData.IsDevirtualized}"); + trace?.Log($"HasProtectedRegions: {MethodData.HasProtectedRegions}"); + trace?.Log($"HasDoNotInlineAttribute: {MethodData.HasDoNotInlineAttribute}"); + trace?.Log($"HasAggressiveInliningAttribute: {MethodData.HasAggressiveInliningAttribute}"); + trace?.Log($"IsMethodImplementationReplaced (Plugged): {MethodData.IsMethodImplementationReplaced}"); + trace?.Log($"CompileCount: {MethodData.CompileCount}"); + + if (StaticCanNotInline(MethodData, Method)) + { + trace?.Log($"** Staticly Evaluated"); + trace?.Log($"Inlined: {MethodData.Inlined}"); + return; + } + + var currentInlineStatus = MethodData.Inlined; + int totalIRCount = 0; int totalNonIRCount = 0; int totalStackParameterInstruction = 0; - if (!MethodCompiler.Method.IsNoInlining) + if (!Method.IsNoInlining) { foreach (var block in BasicBlocks) { @@ -112,14 +127,13 @@ protected override void Run() MethodData.NonIRInstructionCount = totalNonIRCount; MethodData.IRStackParameterInstructionCount = totalStackParameterInstruction; - bool inline = CanInline(MethodData); + bool inline = CanInline(MethodData, Method); MethodData.Inlined = inline; + MethodCompiler.IsMethodInlined = inline; bool triggerReschedules = inline || (currentInlineStatus && !inline); - var timestamp = 0; - if (inline) { MethodData.BasicBlocks = CopyInstructions(); @@ -127,71 +141,73 @@ protected override void Run() if (triggerReschedules) { - timestamp = MethodScheduler.GetTimestamp(); - - MethodScheduler.AddToInlineQueueByCallee(MethodData, timestamp); + MethodScheduler.AddToInlineQueueByCallee(MethodData); } - trace?.Log($"Inlined: {MethodData.Inlined}"); - trace?.Log($"DoNotInline: {MethodData.DoNotInline}"); - trace?.Log($"IsVirtual: {MethodData.IsVirtual}"); - trace?.Log($"IsDevirtualized: {MethodData.IsDevirtualized}"); - trace?.Log($"HasLoops: {MethodData.HasLoops}"); - trace?.Log($"HasProtectedRegions: {MethodData.HasProtectedRegions}"); trace?.Log($"IRInstructionCount: {MethodData.IRInstructionCount}"); trace?.Log($"IRStackParameterInstructionCount: {MethodData.IRStackParameterInstructionCount}"); trace?.Log($"InlinedIRMaximum: {CompilerOptions.InlinedIRMaximum}"); trace?.Log($"NonIRInstructionCount: {MethodData.NonIRInstructionCount}"); - trace?.Log($"HasDoNotInlineAttribute: {MethodData.HasDoNotInlineAttribute}"); - trace?.Log($"HasAggressiveInliningAttribute: {MethodData.HasAggressiveInliningAttribute}"); - trace?.Log($"IsPlugged: {MethodData.IsMethodImplementationReplaced}"); trace?.Log($"HasAddressOfInstruction: {MethodData.HasAddressOfInstruction}"); - trace?.Log($"CompileCount: {MethodData.CompileCount}"); + trace?.Log($"HasLoops: {MethodData.HasLoops}"); + trace?.Log($"** Dynamically Evaluated"); + trace?.Log($"Inlined: {MethodData.Inlined}"); InlinedMethodsCount.Set(inline); ReversedInlinedMethodsCount.Set(MethodData.CompileCount >= MaximumCompileCount); } - public bool CanInline(MethodData method) + public bool StaticCanNotInline(MethodData methodData, MosaMethod method) { - if (method.HasDoNotInlineAttribute) - return false; + if (methodData.HasDoNotInlineAttribute) + return true; - if (method.IsMethodImplementationReplaced) - return false; + if (methodData.IsMethodImplementationReplaced) + return true; - if (method.HasProtectedRegions) - return false; + if (methodData.HasProtectedRegions) + return true; - //if (method.HasLoops) - // return false; + if (methodData.IsVirtual && !methodData.IsDevirtualized) + return true; - if (method.IsVirtual && !method.IsDevirtualized) - return false; + if (methodData.DoNotInline) + return true; - // current implementation limitation - can't include methods with addressOf instruction - if (method.HasAddressOfInstruction) + if (method.DeclaringType.IsValueType + && method.IsVirtual + && !method.IsConstructor + && !method.IsStatic) + return true; + + var returnType = methodData.Method.Signature.ReturnType; + + // FIXME: Add rational + if (MosaTypeLayout.IsStoredOnStack(returnType) && !returnType.IsUI8 && !returnType.IsR8) + return true; + + return false; + } + + public bool CanInline(MethodData methodData, MosaMethod method) + { + if (StaticCanNotInline(methodData, method)) return false; - if (method.NonIRInstructionCount > 0) + // current implementation limitation - can't include methods with addressOf instruction + if (methodData.HasAddressOfInstruction) return false; - if (method.DoNotInline) + if (methodData.NonIRInstructionCount > 0) return false; if (MethodData.CompileCount >= MaximumCompileCount) return false; // too many compiles - cyclic loop suspected - // methods with aggressive inline attribute will double the IR instruction count - int max = method.HasAggressiveInliningAttribute ? (CompilerOptions.InlinedIRMaximum * 2) : CompilerOptions.InlinedIRMaximum; - - if ((method.IRInstructionCount - method.IRStackParameterInstructionCount) > max) - return false; - - var returnType = method.Method.Signature.ReturnType; + // methods with aggressive inline attribute will double the allow IR instruction count + int max = methodData.HasAggressiveInliningAttribute ? (CompilerOptions.InlinedIRMaximum * 2) : CompilerOptions.InlinedIRMaximum; - // FIXME: Add rational - if (MosaTypeLayout.IsStoredOnStack(returnType) && !returnType.IsUI8 && !returnType.IsR8) + if ((methodData.IRInstructionCount - methodData.IRStackParameterInstructionCount) > max) return false; return true; diff --git a/Source/Mosa.Compiler.Framework/Stages/InlineStage.cs b/Source/Mosa.Compiler.Framework/Stages/InlineStage.cs index 2fc5c19152..82613d6c0e 100644 --- a/Source/Mosa.Compiler.Framework/Stages/InlineStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/InlineStage.cs @@ -18,18 +18,12 @@ public class InlineStage : BaseMethodCompilerStage protected override void Initialize() { - Register(InlinedCallSitesCount); + Register(InlinedMethodsCount); Register(InlinedCallSitesCount); } protected override void Run() { - if (HasProtectedRegions) - return; - - if (MethodCompiler.Method.IsCompilerGenerated && MethodCompiler.Method.Name == TypeInitializerStage.TypeInitializerName) - return; - MethodData.CompileCount++; var callSites = new List(); @@ -72,8 +66,6 @@ protected override void Run() var trace = CreateTraceLog("Inlined"); - // Captures point in time - immediately before inlined blocks are used - var timestampStart = MethodScheduler.GetTimestamp(); int callSiteCount = 0; foreach (var callSiteNode in callSites) @@ -106,8 +98,7 @@ protected override void Run() } // Captures point in time - immediately after inlined blocks were used - var timestampEnd = MethodScheduler.GetTimestamp(); - MethodData.InlineTimestamp = timestampStart; + MethodData.InlineTimestamp = MethodScheduler.GetTimestamp(); InlinedMethodsCount.Set(1); InlinedCallSitesCount.Set(callSiteCount); diff --git a/Source/Mosa.Compiler.Framework/Stages/PlugStage.cs b/Source/Mosa.Compiler.Framework/Stages/PlugStage.cs index cc3b10a524..3547a59376 100644 --- a/Source/Mosa.Compiler.Framework/Stages/PlugStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/PlugStage.cs @@ -23,9 +23,9 @@ protected override void Run() { foreach (var block in BasicBlocks) { - for (var node = block.First; !node.IsBlockEndInstruction; node = node.Next) + for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { - if (node.IsEmpty) + if (node.IsEmptyOrNop) continue; if (node.Instruction == IRInstruction.CallStatic diff --git a/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionLayoutStage.cs b/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionLayoutStage.cs index da9c65fcc8..6ad76cda7f 100644 --- a/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionLayoutStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionLayoutStage.cs @@ -45,7 +45,7 @@ private void EmitProtectedRegionTable() { var trace = CreateTraceLog("Regions"); - var protectedRegionTableSymbol = MethodCompiler.Linker.DefineSymbol(Metadata.ProtectedRegionTable + MethodCompiler.Method.FullName, SectionKind.ROData, NativeAlignment, 0); + var protectedRegionTableSymbol = Linker.DefineSymbol(Metadata.ProtectedRegionTable + Method.FullName, SectionKind.ROData, NativeAlignment, 0); var writer = new EndianAwareBinaryWriter(protectedRegionTableSymbol.Stream, Architecture.Endianness); int sectioncount = 0; @@ -82,9 +82,9 @@ private void EmitProtectedRegionTable() sectioncount++; - var name = Metadata.ProtectedRegionTable + MethodCompiler.Method.FullName + "$" + sectioncount.ToString(); + var name = Metadata.ProtectedRegionTable + Method.FullName + "$" + sectioncount.ToString(); var protectedRegionDefinition = CreateProtectedRegionDefinition(name, (uint)start, (uint)end, handler, region.Handler.ExceptionHandlerType, region.Handler.Type); - MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, NativePatchType, protectedRegionTableSymbol, writer.Position, protectedRegionDefinition, 0); + Linker.Link(LinkType.AbsoluteAddress, NativePatchType, protectedRegionTableSymbol, writer.Position, protectedRegionDefinition, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); trace?.Log($" Section: [{start.ToString()}-{end.ToString()}]"); @@ -99,7 +99,7 @@ private void EmitProtectedRegionTable() private LinkerSymbol CreateProtectedRegionDefinition(string name, uint start, uint end, uint handler, ExceptionHandlerType handlerType, MosaType exceptionType) { // Emit parameter table - var protectedRegionDefinitionSymbol = MethodCompiler.Linker.DefineSymbol(name, SectionKind.ROData, 0/*TypeLayout.NativePointerAlignment*/, 0); + var protectedRegionDefinitionSymbol = Linker.DefineSymbol(name, SectionKind.ROData, 0/*TypeLayout.NativePointerAlignment*/, 0); var writer1 = new EndianAwareBinaryWriter(protectedRegionDefinitionSymbol.Stream, Architecture.Endianness); // 1. Offset to start diff --git a/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionStage.cs b/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionStage.cs index 55822752bb..a63e69848d 100644 --- a/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/ProtectedRegionStage.cs @@ -26,12 +26,12 @@ protected override void Run() InsertBlockProtectInstructions(); UpdateBlockProtectInstructions(); - MethodCompiler.ProtectedRegions = ProtectedRegion.CreateProtectedRegions(BasicBlocks, MethodCompiler.Method.ExceptionHandlers); + MethodCompiler.ProtectedRegions = ProtectedRegion.CreateProtectedRegions(BasicBlocks, Method.ExceptionHandlers); } private void InsertBlockProtectInstructions() { - foreach (var handler in MethodCompiler.Method.ExceptionHandlers) + foreach (var handler in Method.ExceptionHandlers) { var tryBlock = BasicBlocks.GetByLabel(handler.TryStart); diff --git a/Source/Mosa.Compiler.Framework/Stages/StackLayoutStage.cs b/Source/Mosa.Compiler.Framework/Stages/StackLayoutStage.cs index ecb3e2bdca..c9192fcb03 100644 --- a/Source/Mosa.Compiler.Framework/Stages/StackLayoutStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/StackLayoutStage.cs @@ -29,7 +29,7 @@ private void LayoutStackVariables() int size = LayoutVariables(MethodCompiler.LocalStack, Architecture.OffsetOfFirstLocal); MethodCompiler.StackSize = size; - MethodCompiler.MethodData.LocalMethodStackSize = -size; + MethodData.LocalMethodStackSize = -size; TraceStackLocals(); } diff --git a/Source/Mosa.Compiler.Framework/Stages/UnboxValueTypeStage.cs b/Source/Mosa.Compiler.Framework/Stages/UnboxValueTypeStage.cs index aed30a7532..0f82b23766 100644 --- a/Source/Mosa.Compiler.Framework/Stages/UnboxValueTypeStage.cs +++ b/Source/Mosa.Compiler.Framework/Stages/UnboxValueTypeStage.cs @@ -13,22 +13,21 @@ public class UnboxValueTypeStage : BaseMethodCompilerStage protected override void Run() { - // The method declaring type must be a valuetype - if (!MethodCompiler.Type.IsValueType) - return; - - // If the method is static, non-virtual or is a constructor then don't process - if (Method.IsStatic || !Method.IsVirtual || Method.IsConstructor) - return; - - // If the method does not belong to an interface then don't process - if (!(IsInterfaceMethod() || OverridesMethod())) + // The method declaring type must be a valuetype, not a constructor, or static method, or not virual + if (!Method.DeclaringType.IsValueType + || Method.IsConstructor + || Method.IsStatic + || !Method.IsVirtual) return; // If the method is empty then don't process if (BasicBlocks.PrologueBlock.NextBlocks.Count == 0 || BasicBlocks.PrologueBlock.NextBlocks[0] == BasicBlocks.EpilogueBlock) return; + //// If the method does not belong to an interface then don't process + //if (!(OverridesMethod() || IsInterfaceMethod())) + // return; + TriggeredCount.Set(1); // Get the this pointer @@ -47,31 +46,31 @@ protected override void Run() context.AppendInstruction(Select(IRInstruction.StoreInt32, IRInstruction.StoreInt64), null, StackFrame, thisPtr, v1); } - private bool IsInterfaceMethod() - { - foreach (var iface in MethodCompiler.Type.Interfaces) - { - foreach (var method in TypeLayout.GetInterfaceTable(MethodCompiler.Type, iface)) - { - if (method == MethodCompiler.Method) - return true; - } - } + //private bool IsInterfaceMethod() + //{ + // foreach (var iface in MethodCompiler.Type.Interfaces) + // { + // foreach (var method in TypeLayout.GetInterfaceTable(MethodCompiler.Type, iface)) + // { + // if (method == MethodCompiler.Method) + // return true; + // } + // } - return false; - } + // return false; + //} - private bool OverridesMethod() - { - if (MethodCompiler.Method.Overrides == null) - return false; - if (MethodCompiler.Type.BaseType.Name.Equals("ValueType")) - return true; - if (MethodCompiler.Type.BaseType.Name.Equals("Object")) - return true; - if (MethodCompiler.Type.BaseType.Name.Equals("Enum")) - return true; - return false; - } + //private bool OverridesMethod() + //{ + // if (Method.Overrides == null) + // return false; + // if (MethodCompiler.Type.BaseType.Name.Equals("ValueType")) + // return true; + // if (MethodCompiler.Type.BaseType.Name.Equals("Object")) + // return true; + // if (MethodCompiler.Type.BaseType.Name.Equals("Enum")) + // return true; + // return false; + //} } } diff --git a/Source/Mosa.Platform.Intel/CompilerStages/MultibootV1Stage.cs b/Source/Mosa.Platform.Intel/CompilerStages/MultibootV1Stage.cs index 1ceb89660a..9422f4fece 100644 --- a/Source/Mosa.Platform.Intel/CompilerStages/MultibootV1Stage.cs +++ b/Source/Mosa.Platform.Intel/CompilerStages/MultibootV1Stage.cs @@ -100,11 +100,13 @@ protected override void Setup() Linker.EntryPoint = Linker.GetSymbol(multibootMethod.FullName); + Compiler.CompilerData.GetMethodData(multibootMethod).DoNotInline = true; MethodScanner.MethodInvoked(multibootMethod, multibootMethod); var startUpType = TypeSystem.GetTypeByName("Mosa.Runtime", "StartUp"); var initializeMethod = startUpType.FindMethodByName("Initialize"); + Compiler.CompilerData.GetMethodData(initializeMethod).DoNotInline = true; MethodScanner.MethodInvoked(initializeMethod, multibootMethod); } diff --git a/Source/Mosa.Platform.Intel/CompilerStages/StartUpStage.cs b/Source/Mosa.Platform.Intel/CompilerStages/StartUpStage.cs index 4fa12de4af..92fa1d8b1a 100644 --- a/Source/Mosa.Platform.Intel/CompilerStages/StartUpStage.cs +++ b/Source/Mosa.Platform.Intel/CompilerStages/StartUpStage.cs @@ -26,6 +26,8 @@ protected override void Setup() Linker.EntryPoint = Linker.GetSymbol(initializeMethod.FullName); + Compiler.CompilerData.GetMethodData(initializeMethod).DoNotInline = true; + MethodScanner.MethodInvoked(initializeMethod, initializeMethod); } else diff --git a/Source/Mosa.Platform.Intel/Stages/FloatingPointStage.cs b/Source/Mosa.Platform.Intel/Stages/FloatingPointStage.cs index 043c0e18a4..383a91c152 100644 --- a/Source/Mosa.Platform.Intel/Stages/FloatingPointStage.cs +++ b/Source/Mosa.Platform.Intel/Stages/FloatingPointStage.cs @@ -61,13 +61,13 @@ protected void FixConstantIntegerToFloat(InstructionNode node) if (result.IsR4) { - var symbol = MethodCompiler.Linker.GetConstantSymbol((float)source.ConstantUnsignedLongInteger); + var symbol = Linker.GetConstantSymbol((float)source.ConstantUnsignedLongInteger); var label = Operand.CreateLabel(result.Type, symbol.Name); node.SetInstruction(MovssLoad, result, label, ConstantZero); } else if (result.IsR8) { - var symbol = MethodCompiler.Linker.GetConstantSymbol((double)source.ConstantUnsignedLongInteger); + var symbol = Linker.GetConstantSymbol((double)source.ConstantUnsignedLongInteger); var label = Operand.CreateLabel(result.Type, symbol.Name); node.SetInstruction(MovsdLoad, result, label, ConstantZero); } @@ -95,13 +95,13 @@ protected void EmitFloatingPointConstants(InstructionNode node) if (operand.IsR4) { - var symbol = MethodCompiler.Linker.GetConstantSymbol(operand.ConstantSingleFloatingPoint); + var symbol = Linker.GetConstantSymbol(operand.ConstantSingleFloatingPoint); var label = Operand.CreateLabel(operand.Type, symbol.Name); before.SetInstruction(MovssLoad, v1, label, ConstantZero); } else { - var symbol = MethodCompiler.Linker.GetConstantSymbol(operand.ConstantDoubleFloatingPoint); + var symbol = Linker.GetConstantSymbol(operand.ConstantDoubleFloatingPoint); var label = Operand.CreateLabel(operand.Type, symbol.Name); before.SetInstruction(MovsdLoad, v1, label, ConstantZero); } diff --git a/Source/Mosa.Tool.Explorer/MainForm.cs b/Source/Mosa.Tool.Explorer/MainForm.cs index 28336a6364..451dfd4e31 100644 --- a/Source/Mosa.Tool.Explorer/MainForm.cs +++ b/Source/Mosa.Tool.Explorer/MainForm.cs @@ -602,7 +602,7 @@ private void UpdateStages() cbStages.Items.Add(stage); } - cbStages.SelectedIndex = 0; + cbStages.SelectedIndex = cbStages.Items.Count == 0 ? -1 : 0; } private void UpdateDebugStages() diff --git a/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs b/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs index 272fc91626..e98df8957f 100644 --- a/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs +++ b/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs @@ -43,7 +43,7 @@ protected void TraceDisassembly() } // Create a byte array from the symbol stream - var symbol = MethodCompiler.Linker.GetSymbol(MethodCompiler.Method.FullName); + var symbol = Linker.GetSymbol(Method.FullName); var stream = symbol.Stream; var oldPosition = stream.Position; var length = (int)stream.Length; @@ -88,7 +88,7 @@ protected void TracePatchRequests() if (trace == null) return; - var symbol = MethodCompiler.Linker.GetSymbol(MethodCompiler.Method.FullName); + var symbol = Linker.GetSymbol(Method.FullName); foreach (var request in symbol.GetLinkRequests()) { diff --git a/Source/Mosa.UnitTests/OptimizationTests.cs b/Source/Mosa.UnitTests/OptimizationTests.cs index 48aa27487e..17c2672c7d 100644 --- a/Source/Mosa.UnitTests/OptimizationTests.cs +++ b/Source/Mosa.UnitTests/OptimizationTests.cs @@ -283,5 +283,23 @@ public static bool OptimizationTest21(byte a) b |= 3; return b != 0; } + + //[MosaUnitTest(0)] + //[MosaUnitTest(1)] + //[MosaUnitTest(2)] + //[MosaUnitTest(3)] + //public static int OptimizationTest22(int a) + //{ + // return a % 2 != 0 ? 4 : 2; + //} + + //[MosaUnitTest((uint)0)] + //[MosaUnitTest((uint)1)] + //[MosaUnitTest((uint)2)] + //[MosaUnitTest((uint)3)] + //public static uint OptimizationTest23(uint a) + //{ + // return a % 2 != 0 ? 4u : 2u; + //} } } diff --git a/Source/Mosa.Utility.Launcher/Builder.cs b/Source/Mosa.Utility.Launcher/Builder.cs index f0395cbdf3..1e72d55bbe 100644 --- a/Source/Mosa.Utility.Launcher/Builder.cs +++ b/Source/Mosa.Utility.Launcher/Builder.cs @@ -415,14 +415,17 @@ private void GenerateASMFile() var textSection = Linker.Sections[(int)SectionKind.Text]; - var map = new Dictionary(); + var map = new Dictionary>(); foreach (var symbol in Linker.Symbols) { - if (map.ContainsKey(symbol.VirtualAddress)) - continue; + if (!map.TryGetValue(symbol.VirtualAddress, out List list)) + { + list = new List(); + map.Add(symbol.VirtualAddress, list); + } - map.Add(symbol.VirtualAddress, symbol.Name); + list.Add(symbol.Name); } const uint multibootHeaderLength = MultibootHeaderLength; @@ -443,9 +446,12 @@ private void GenerateASMFile() { using (var dest = File.CreateText(asmfile)) { - if (map.ContainsKey(startingAddress)) + if (map.TryGetValue(startingAddress, out List list)) { - dest.WriteLine("; " + map[startingAddress]); + foreach (var entry in list) + { + dest.WriteLine($"; {entry}"); + } } foreach (var instruction in disasm.Disassemble()) @@ -453,9 +459,12 @@ private void GenerateASMFile() var inst = translator.Translate(instruction); dest.WriteLine(inst); - if (map.ContainsKey(instruction.PC)) + if (map.TryGetValue(instruction.PC, out List list2)) { - dest.WriteLine("; " + map[instruction.PC]); + foreach (var entry in list2) + { + dest.WriteLine($"; {entry}"); + } } if (instruction.PC > startingAddress + length) diff --git a/Source/Mosa.Utility.UnitTests/UnitTestEngine.cs b/Source/Mosa.Utility.UnitTests/UnitTestEngine.cs index 92277a9002..b6d2629374 100644 --- a/Source/Mosa.Utility.UnitTests/UnitTestEngine.cs +++ b/Source/Mosa.Utility.UnitTests/UnitTestEngine.cs @@ -93,7 +93,7 @@ public UnitTestEngine(bool display = false) GenerateNASMFile = false, GenerateASMFile = true, GenerateMapFile = true, - GenerateDebugFile = false, + GenerateDebugFile = true, PlugKorlib = true, NoDisplay = !display };