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
};