Cosmos/source2/IL2CPU/Cosmos.IL2CPU.X86/AppAssembler.cs
blah38621_cp 1b922726f0 The first of a series of commits as I work my way down the list of things Gendarme found wrong. (a large amount is likely to be skipped, as gendarme found 13k potential issues.)
This one makes sure that constructors for abstract classes are protected, not public, as the constructor can only be called by child classes.
2011-10-22 23:19:51 +00:00

156 lines
No EOL
6.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Cosmos.Compiler.Assembler;
using Cosmos.Compiler.Assembler.X86;
using CPU = Cosmos.Compiler.Assembler;
using CPUx86 = Cosmos.Compiler.Assembler.X86;
namespace Cosmos.IL2CPU.X86 {
public abstract class AppAssembler : IL2CPU.AppAssembler {
public const string EndOfMethodLabelNameNormal = ".END__OF__METHOD_NORMAL";
public const string EndOfMethodLabelNameException = ".END__OF__METHOD_EXCEPTION";
protected AppAssembler(byte comportNumber)
: base(new AssemblerNasm(comportNumber)) {
}
protected override void Move(string aDestLabelName, int aValue) {
new CPUx86.Move {
DestinationRef = CPU.ElementReference.New(aDestLabelName),
DestinationIsIndirect = true,
SourceValue = (uint)aValue
};
}
protected override void Push(uint aValue) {
new CPUx86.Push {
DestinationValue = aValue
};
}
protected override void Pop() {
new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)mAssembler.Stack.Pop().Size };
}
protected override void Push(string aLabelName, bool isIndirect = false) {
new CPUx86.Push {
DestinationRef = CPU.ElementReference.New(aLabelName),
DestinationIsIndirect = isIndirect
};
}
protected override void Call(MethodBase aMethod) {
new Compiler.Assembler.X86.Call {
DestinationLabel = CPU.MethodInfoLabelGenerator.GenerateLabelName(aMethod)
};
}
protected override void Jump(string aLabelName) {
new Compiler.Assembler.X86.Jump {
DestinationLabel = aLabelName
};
}
protected override int GetVTableEntrySize() {
return 16; // todo: retrieve from actual type info
}
private const string InitStringIDsLabel = "___INIT__STRINGS_TYPE_ID_S___";
public override void EmitEntrypoint(MethodBase aEntrypoint, IEnumerable<MethodBase> aMethods) {
#region Literal strings fixup code
// at the time the datamembers for literal strings are created, the type id for string is not yet determined.
// for now, we fix this at runtime.
new Label(InitStringIDsLabel);
new Push { DestinationReg = Registers.EBP };
new Move { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
new Move { DestinationReg = Registers.EAX, SourceRef = ElementReference.New(ILOp.GetTypeIDLabel(typeof(String))), SourceIsIndirect = true };
foreach (var xDataMember in mAssembler.DataMembers) {
if (!xDataMember.Name.StartsWith("StringLiteral")) {
continue;
}
if (xDataMember.Name.EndsWith("__Contents")) {
continue;
}
new Move { DestinationRef = ElementReference.New(xDataMember.Name), DestinationIsIndirect = true, SourceReg = Registers.EAX };
}
new Pop { DestinationReg = Registers.EBP };
new Return();
#endregion
new Label(CosmosAssembler.EntryPointName);
new Push { DestinationReg = Registers.EBP };
new Move { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
new Call { DestinationLabel = InitVMTCodeLabel };
new Call { DestinationLabel = InitStringIDsLabel };
// we now need to do "newobj" on the entry point, and after that, call .Start on it
var xCurLabel = CosmosAssembler.EntryPointName + ".CreateEntrypoint";
new Label(xCurLabel);
IL.Newobj.Assemble(Assembler.CurrentInstance, null, null, xCurLabel, aEntrypoint.DeclaringType, aEntrypoint);
xCurLabel = CosmosAssembler.EntryPointName + ".CallStart";
new Label(xCurLabel);
IL.Call.DoExecute(mAssembler, null, aEntrypoint.DeclaringType.BaseType.GetMethod("Start"), null, xCurLabel, CosmosAssembler.EntryPointName + ".AfterStart");
new Label(CosmosAssembler.EntryPointName + ".AfterStart");
new Pop { DestinationReg = Registers.EBP };
new Return();
if (ShouldOptimize)
{
Orvid.Optimizer.Optimize(Assembler);
}
}
protected override void Ldarg(MethodInfo aMethod, int aIndex) {
IL.Ldarg.DoExecute(mAssembler, aMethod, (ushort)aIndex);
}
protected override void Call(MethodInfo aMethod, MethodInfo aTargetMethod) {
var xSize = IL.Call.GetStackSizeToReservate(aTargetMethod.MethodBase);
if (xSize > 0) {
new CPUx86.Sub { DestinationReg = Registers.ESP, SourceValue = xSize };
}
new CPUx86.Call { DestinationLabel = ILOp.GetMethodLabel(aTargetMethod) };
}
protected override void Ldflda(MethodInfo aMethod, string aFieldId) {
IL.Ldflda.DoExecute(mAssembler, aMethod, aMethod.MethodBase.DeclaringType, aFieldId, false);
}
//// todo: remove when everything goes fine
//protected override void AfterOp(MethodInfo aMethod, ILOpCode aOpCode) {
// base.AfterOp(aMethod, aOpCode);
// new Move { DestinationReg = Registers.EAX, SourceReg = Registers.EBP };
// var xTotalTransitionalStackSize = (from item in Stack
// select (int)ILOp.Align((uint)item.Size, 4)).Sum();
// // include locals too
// if (aMethod.MethodBase.DeclaringType.Name == "GCImplementationImpl"
// && aMethod.MethodBase.Name == "AllocNewObject") {
// Console.Write("");
// }
// var xLocalsValue = (from item in aMethod.MethodBase.GetMethodBody().LocalVariables
// select (int)ILOp.Align(ILOp.SizeOfType(item.LocalType), 4)).Sum();
// var xExtraSize = xLocalsValue + xTotalTransitionalStackSize;
// new Sub { DestinationReg = Registers.EAX, SourceValue = (uint)xExtraSize };
// new Compare { DestinationReg = Registers.EAX, SourceReg = Registers.ESP };
// var xLabel = ILOp.GetLabel(aMethod, aOpCode) + "___TEMP__STACK_CHECK";
// new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = xLabel };
// new Xchg { DestinationReg = Registers.BX, SourceReg = Registers.BX, Size = 16 };
// new Halt();
// new Label(xLabel);
//}
public override uint GetSizeOfType(Type aType) {
return ILOp.SizeOfType(aType);
}
}
}