Fixed DataMember to handle long / ulong values (that is the correct NASM type 'dq' is emitted)

This commit is contained in:
fanoI 2016-08-25 15:43:52 +02:00
parent b16b034ff9
commit 0dbb621c5d

View file

@ -5,8 +5,10 @@ using System.Text;
using System.Reflection; using System.Reflection;
using System.IO; using System.IO;
namespace Cosmos.Assembler { namespace Cosmos.Assembler
public class DataMember : BaseAssemblerElement, IComparable<DataMember> { {
public class DataMember : BaseAssemblerElement, IComparable<DataMember>
{
public string Name { get; private set; } public string Name { get; private set; }
public bool IsComment { get; set; } public bool IsComment { get; set; }
public byte[] RawDefaultValue { get; set; } public byte[] RawDefaultValue { get; set; }
@ -15,15 +17,18 @@ namespace Cosmos.Assembler {
public string RawAsm = null; public string RawAsm = null;
// Hack for not to emit raw data. See RawAsm // Hack for not to emit raw data. See RawAsm
public DataMember() { public DataMember()
{
Name = "Dummy"; Name = "Dummy";
} }
protected DataMember(string aName) { protected DataMember(string aName)
{
Name = aName; Name = aName;
} }
public DataMember(string aName, string aValue) { public DataMember(string aName, string aValue)
{
Name = aName; Name = aName;
var xBytes = ASCIIEncoding.ASCII.GetBytes(aValue); var xBytes = ASCIIEncoding.ASCII.GetBytes(aValue);
var xBytes2 = new byte[xBytes.Length + 1]; var xBytes2 = new byte[xBytes.Length + 1];
@ -32,84 +37,104 @@ namespace Cosmos.Assembler {
RawDefaultValue = xBytes2; RawDefaultValue = xBytes2;
} }
public DataMember(string aName, params object[] aDefaultValue) { public DataMember(string aName, params object[] aDefaultValue)
{
Name = aName; Name = aName;
UntypedDefaultValue = aDefaultValue; UntypedDefaultValue = aDefaultValue;
} }
public DataMember(string aName, byte[] aDefaultValue) { public DataMember(string aName, byte[] aDefaultValue)
{
Name = aName; Name = aName;
RawDefaultValue = aDefaultValue; RawDefaultValue = aDefaultValue;
//UntypedDefaultValue = aDefaultValue; //UntypedDefaultValue = aDefaultValue;
} }
public DataMember(string aName, short[] aDefaultValue) { // TODO Why not use <Cast> here too and instead to pack the short array into an Int32 array simply emit it with dw?
public DataMember(string aName, short[] aDefaultValue)
{
Name = aName; Name = aName;
RawDefaultValue = new byte[aDefaultValue.Length * 2]; RawDefaultValue = new byte[aDefaultValue.Length * 2];
for (int i = 0; i < aDefaultValue.Length; i++) { for (int i = 0; i < aDefaultValue.Length; i++)
{
Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0, Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0,
RawDefaultValue, i * 2, 2); RawDefaultValue, i * 2, 2);
} }
//UntypedDefaultValue = aDefaultValue; //UntypedDefaultValue = aDefaultValue;
} }
public DataMember(string aName, params ushort[] aDefaultValue) { // TODO Why not use <Cast> here too and instead to pack the short array into an Int32 array simply emit it with dw?
public DataMember(string aName, params ushort[] aDefaultValue)
{
Name = aName; Name = aName;
RawDefaultValue = new byte[aDefaultValue.Length * 2]; RawDefaultValue = new byte[aDefaultValue.Length * 2];
for (int i = 0; i < aDefaultValue.Length; i++) { for (int i = 0; i < aDefaultValue.Length; i++)
{
Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0, Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0,
RawDefaultValue, i * 2, 2); RawDefaultValue, i * 2, 2);
} }
//UntypedDefaultValue = aDefaultValue; //UntypedDefaultValue = aDefaultValue;
} }
public DataMember(string aName, params uint[] aDefaultValue) { public DataMember(string aName, params uint[] aDefaultValue)
{
Name = aName; Name = aName;
//RawDefaultValue = new byte[aDefaultValue.Length * 4];
//for (int i = 0; i < aDefaultValue.Length; i++) {
// Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0,
// RawDefaultValue, i * 4, 4);
//}
UntypedDefaultValue = aDefaultValue.Cast<object>().ToArray(); UntypedDefaultValue = aDefaultValue.Cast<object>().ToArray();
} }
public DataMember(string aName, params int[] aDefaultValue) { public DataMember(string aName, params int[] aDefaultValue)
{
Name = aName; Name = aName;
//RawDefaultValue = new byte[aDefaultValue.Length * 4];
//for (int i = 0; i < aDefaultValue.Length; i++) {
// Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0,
// RawDefaultValue, i * 4, 4);
//}
UntypedDefaultValue = aDefaultValue.Cast<object>().ToArray(); UntypedDefaultValue = aDefaultValue.Cast<object>().ToArray();
} }
public DataMember(string aName, Stream aData) { public DataMember(string aName, params ulong[] aDefaultValue)
{
Name = aName;
UntypedDefaultValue = aDefaultValue.Cast<object>().ToArray();
}
public DataMember(string aName, params long[] aDefaultValue)
{
Name = aName;
UntypedDefaultValue = aDefaultValue.Cast<object>().ToArray();
}
public DataMember(string aName, Stream aData)
{
Name = aName; Name = aName;
RawDefaultValue = new byte[aData.Length]; RawDefaultValue = new byte[aData.Length];
aData.Read(RawDefaultValue, 0, RawDefaultValue.Length); aData.Read(RawDefaultValue, 0, RawDefaultValue.Length);
} }
public static string GetStaticFieldName(FieldInfo aField) { public static string GetStaticFieldName(FieldInfo aField)
{
return FilterStringForIncorrectChars("static_field__" + LabelName.GetFullName(aField.DeclaringType) + "." + aField.Name); return FilterStringForIncorrectChars("static_field__" + LabelName.GetFullName(aField.DeclaringType) + "." + aField.Name);
} }
public const string IllegalIdentifierChars = "&.,+$<>{}-`\'/\\ ()[]*!="; public const string IllegalIdentifierChars = "&.,+$<>{}-`\'/\\ ()[]*!=";
public static string FilterStringForIncorrectChars(string aName) { public static string FilterStringForIncorrectChars(string aName)
{
string xTempResult = aName; string xTempResult = aName;
foreach (char c in IllegalIdentifierChars) { foreach (char c in IllegalIdentifierChars)
{
xTempResult = xTempResult.Replace(c, '_'); xTempResult = xTempResult.Replace(c, '_');
} }
return String.Intern(xTempResult); return String.Intern(xTempResult);
} }
public override void WriteText(Cosmos.Assembler.Assembler aAssembler, TextWriter aOutput) { public override void WriteText(Cosmos.Assembler.Assembler aAssembler, TextWriter aOutput)
if (RawAsm != null) { {
if (RawAsm != null)
{
aOutput.WriteLine(RawAsm); aOutput.WriteLine(RawAsm);
return; return;
} }
if (RawDefaultValue != null) { if (RawDefaultValue != null)
if (RawDefaultValue.Length == 0) { {
if (RawDefaultValue.Length == 0)
{
aOutput.Write(Name); aOutput.Write(Name);
aOutput.Write(":"); aOutput.Write(":");
return; return;
@ -117,19 +142,24 @@ namespace Cosmos.Assembler {
if ((from item in RawDefaultValue if ((from item in RawDefaultValue
group item by item group item by item
into i into i
select i).Count() > 1 || RawDefaultValue.Length < 250) { select i).Count() > 1 || RawDefaultValue.Length < 250)
if (IsGlobal) { {
if (IsGlobal)
{
aOutput.Write("global "); aOutput.Write("global ");
aOutput.WriteLine(Name); aOutput.WriteLine(Name);
} }
aOutput.Write(Name); aOutput.Write(Name);
aOutput.Write(" db "); aOutput.Write(" db ");
for (int i = 0; i < (RawDefaultValue.Length - 1); i++) { for (int i = 0; i < (RawDefaultValue.Length - 1); i++)
{
aOutput.Write(RawDefaultValue[i]); aOutput.Write(RawDefaultValue[i]);
aOutput.Write(", "); aOutput.Write(", ");
} }
aOutput.Write(RawDefaultValue.Last()); aOutput.Write(RawDefaultValue.Last());
} else { }
else
{
//aOutputWriter.WriteLine("TIMES 0x50000 db 0"); //aOutputWriter.WriteLine("TIMES 0x50000 db 0");
aOutput.Write("global "); aOutput.Write("global ");
aOutput.WriteLine(Name); aOutput.WriteLine(Name);
@ -141,26 +171,41 @@ namespace Cosmos.Assembler {
} }
return; return;
} }
if (UntypedDefaultValue != null) { if (UntypedDefaultValue != null)
{
StringBuilder xSB = new StringBuilder(); StringBuilder xSB = new StringBuilder();
if (IsGlobal) { if (IsGlobal)
{
aOutput.Write("global "); aOutput.Write("global ");
aOutput.WriteLine(Name); aOutput.WriteLine(Name);
} }
//aOutput.WriteLine("; Type of UntypedDefaultValue is " + UntypedDefaultValue[0].GetType());
aOutput.Write(Name); aOutput.Write(Name);
if (UntypedDefaultValue[0] is Int64 || UntypedDefaultValue[0] is UInt64 || UntypedDefaultValue[0] is Double)
aOutput.Write(" dq ");
else
aOutput.Write(" dd "); aOutput.Write(" dd ");
Func<object, string> xGetTextForItem = delegate(object aItem) {
Func<object, string> xGetTextForItem = delegate (object aItem)
{
var xElementRef = aItem as Cosmos.Assembler.ElementReference; var xElementRef = aItem as Cosmos.Assembler.ElementReference;
if (xElementRef == null) { if (xElementRef == null)
{
return (aItem ?? 0).ToString(); return (aItem ?? 0).ToString();
} else { }
if (xElementRef.Offset == 0) { else
{
if (xElementRef.Offset == 0)
{
return xElementRef.Name; return xElementRef.Name;
} }
return xElementRef.Name + " + " + xElementRef.Offset; return xElementRef.Name + " + " + xElementRef.Offset;
} }
}; };
for (int i = 0; i < (UntypedDefaultValue.Length - 1); i++) { for (int i = 0; i < (UntypedDefaultValue.Length - 1); i++)
{
aOutput.Write(xGetTextForItem(UntypedDefaultValue[i])); aOutput.Write(xGetTextForItem(UntypedDefaultValue[i]));
aOutput.Write(", "); aOutput.Write(", ");
} }
@ -170,52 +215,68 @@ namespace Cosmos.Assembler {
throw new Exception("Situation unsupported!"); throw new Exception("Situation unsupported!");
} }
public int CompareTo(DataMember other) { public int CompareTo(DataMember other)
{
return String.Compare(Name, other.Name); return String.Compare(Name, other.Name);
} }
public bool IsGlobal { public bool IsGlobal
{
get; get;
set; set;
} }
public override ulong? ActualAddress { public override ulong? ActualAddress
get { {
get
{
// TODO: for now, we dont have any data alignment // TODO: for now, we dont have any data alignment
return StartAddress; return StartAddress;
} }
} }
public override void UpdateAddress(Cosmos.Assembler.Assembler aAssembler, ref ulong xAddress) { public override void UpdateAddress(Cosmos.Assembler.Assembler aAssembler, ref ulong xAddress)
if (Alignment > 0) { {
if (xAddress % Alignment != 0) { if (Alignment > 0)
{
if (xAddress % Alignment != 0)
{
xAddress += Alignment - (xAddress % Alignment); xAddress += Alignment - (xAddress % Alignment);
} }
} }
base.UpdateAddress(aAssembler, ref xAddress); base.UpdateAddress(aAssembler, ref xAddress);
if (RawDefaultValue != null) { if (RawDefaultValue != null)
{
xAddress += (ulong)RawDefaultValue.LongLength; xAddress += (ulong)RawDefaultValue.LongLength;
} }
if (UntypedDefaultValue != null) { if (UntypedDefaultValue != null)
{
// TODO: what to do with 64bit target platforms? right now we only support 32bit // TODO: what to do with 64bit target platforms? right now we only support 32bit
xAddress += (ulong)(UntypedDefaultValue.LongLength * 4); xAddress += (ulong)(UntypedDefaultValue.LongLength * 4);
} }
} }
public override bool IsComplete(Assembler aAssembler) { public override bool IsComplete(Assembler aAssembler)
if (RawAsm != null) { {
if (RawAsm != null)
{
return true; return true;
} }
if (UntypedDefaultValue != null && if (UntypedDefaultValue != null &&
UntypedDefaultValue.LongLength > 0) { UntypedDefaultValue.LongLength > 0)
{
foreach (var xReference in (from item in UntypedDefaultValue foreach (var xReference in (from item in UntypedDefaultValue
let xRef = item as Cosmos.Assembler.ElementReference let xRef = item as Cosmos.Assembler.ElementReference
where xRef != null where xRef != null
select xRef)) { select xRef))
{
var xRef = aAssembler.TryResolveReference(xReference); var xRef = aAssembler.TryResolveReference(xReference);
if (xRef == null) { if (xRef == null)
{
return false; return false;
} else if (!xRef.IsComplete(aAssembler)) { }
else if (!xRef.IsComplete(aAssembler))
{
return false; return false;
} }
} }
@ -223,40 +284,56 @@ namespace Cosmos.Assembler {
return true; return true;
} }
public override void WriteData(Cosmos.Assembler.Assembler aAssembler, Stream aOutput) { public override void WriteData(Cosmos.Assembler.Assembler aAssembler, Stream aOutput)
{
if (UntypedDefaultValue != null && if (UntypedDefaultValue != null &&
UntypedDefaultValue.LongLength > 0) { UntypedDefaultValue.LongLength > 0)
{
//var xBuff = (byte[])Array.CreateInstance(typeof(byte), UntypedDefaultValue.LongLength * 4); //var xBuff = (byte[])Array.CreateInstance(typeof(byte), UntypedDefaultValue.LongLength * 4);
for (int i = 0; i < UntypedDefaultValue.Length; i++) { for (int i = 0; i < UntypedDefaultValue.Length; i++)
{
var xRef = UntypedDefaultValue[i] as Cosmos.Assembler.ElementReference; var xRef = UntypedDefaultValue[i] as Cosmos.Assembler.ElementReference;
//byte[] xTemp; //byte[] xTemp;
if (xRef != null) { if (xRef != null)
{
var xTheRef = aAssembler.TryResolveReference(xRef); var xTheRef = aAssembler.TryResolveReference(xRef);
if (xTheRef == null) { if (xTheRef == null)
{
throw new Exception("Reference not found!"); throw new Exception("Reference not found!");
} }
if (!xTheRef.ActualAddress.HasValue) { if (!xTheRef.ActualAddress.HasValue)
{
Console.Write(""); Console.Write("");
} }
aOutput.Write(BitConverter.GetBytes(xTheRef.ActualAddress.Value), 0, 4); aOutput.Write(BitConverter.GetBytes(xTheRef.ActualAddress.Value), 0, 4);
//xTemp = BitConverter.GetBytes(); //xTemp = BitConverter.GetBytes();
} else { }
if (UntypedDefaultValue[i] is int) { else
{
if (UntypedDefaultValue[i] is int)
{
aOutput.Write(BitConverter.GetBytes((int)UntypedDefaultValue[i]), 0, 4); aOutput.Write(BitConverter.GetBytes((int)UntypedDefaultValue[i]), 0, 4);
//xTemp = BitConverter.GetBytes((int)UntypedDefaultValue[i]); //xTemp = BitConverter.GetBytes((int)UntypedDefaultValue[i]);
} else { }
if (UntypedDefaultValue[i] is uint) { else
{
if (UntypedDefaultValue[i] is uint)
{
aOutput.Write(BitConverter.GetBytes((uint)UntypedDefaultValue[i]), 0, 4); aOutput.Write(BitConverter.GetBytes((uint)UntypedDefaultValue[i]), 0, 4);
//xTemp = BitConverter.GetBytes((uint)UntypedDefaultValue[i]); //xTemp = BitConverter.GetBytes((uint)UntypedDefaultValue[i]);
} else { }
else
{
throw new Exception("Invalid value inside UntypedDefaultValue"); throw new Exception("Invalid value inside UntypedDefaultValue");
} }
} }
} }
//Array.Copy(xTemp, 0, xBuff, i * 4, 4); //Array.Copy(xTemp, 0, xBuff, i * 4, 4);
} }
} else { }
else
{
aOutput.Write(RawDefaultValue, 0, RawDefaultValue.Length); aOutput.Write(RawDefaultValue, 0, RawDefaultValue.Length);
} }
} }