mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-21 13:28:41 +00:00
271 lines
11 KiB
C#
271 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Reflection;
|
|
using System.IO;
|
|
|
|
namespace Indy.IL2CPU.Assembler {
|
|
public class DataMember: BaseAssemblerElement, IComparable<DataMember> {
|
|
public const string IllegalIdentifierChars = "&.,+$<>{}-`\'/\\ ()[]*!=";
|
|
public static string GetStaticFieldName(FieldInfo aField) {
|
|
return FilterStringForIncorrectChars("static_field__" + aField.DeclaringType.FullName + "." + aField.Name);
|
|
}
|
|
|
|
public static string FilterStringForIncorrectChars(string aName) {
|
|
string xTempResult = aName;
|
|
foreach (char c in IllegalIdentifierChars) {
|
|
xTempResult = xTempResult.Replace(c, '_');
|
|
}
|
|
return xTempResult;
|
|
}
|
|
|
|
public DataMember(string aName, Stream aData) {
|
|
Name = aName;
|
|
RawDefaultValue = new byte[aData.Length];
|
|
aData.Read(RawDefaultValue,
|
|
0,
|
|
RawDefaultValue.Length);
|
|
}
|
|
|
|
public byte[] RawDefaultValue {
|
|
get;
|
|
set;
|
|
}
|
|
public uint Alignment {
|
|
get;
|
|
set;
|
|
}
|
|
|
|
private object[] UntypedDefaultValue;
|
|
|
|
public DataMember(string aName, params object[] aDefaultValue) {
|
|
Name = aName;
|
|
UntypedDefaultValue = aDefaultValue;
|
|
}
|
|
|
|
public DataMember(string aName, byte[] aDefaultValue) {
|
|
Name = aName;
|
|
RawDefaultValue = aDefaultValue;
|
|
//UntypedDefaultValue = aDefaultValue;
|
|
}
|
|
|
|
public DataMember(string aName, short[] aDefaultValue) {
|
|
Name = aName;
|
|
RawDefaultValue = new byte[aDefaultValue.Length * 2];
|
|
for (int i = 0; i < aDefaultValue.Length; i++) {
|
|
Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0,
|
|
RawDefaultValue, i * 2, 2);
|
|
}
|
|
//UntypedDefaultValue = aDefaultValue;
|
|
}
|
|
|
|
public DataMember(string aName, params ushort[] aDefaultValue) {
|
|
Name = aName;
|
|
RawDefaultValue = new byte[aDefaultValue.Length * 2];
|
|
for (int i = 0; i < aDefaultValue.Length; i++) {
|
|
Array.Copy(BitConverter.GetBytes(aDefaultValue[i]), 0,
|
|
RawDefaultValue, i * 2, 2);
|
|
}
|
|
//UntypedDefaultValue = aDefaultValue;
|
|
}
|
|
|
|
public DataMember(string aName, params uint[] aDefaultValue) {
|
|
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();
|
|
}
|
|
|
|
public DataMember(string aName, params int[] aDefaultValue) {
|
|
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();
|
|
}
|
|
|
|
public string Name {
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public override string ToString() {
|
|
if(RawDefaultValue!=null) {
|
|
if(RawDefaultValue.Length==0) {
|
|
return Name + ":";
|
|
}
|
|
if ((from item in RawDefaultValue
|
|
group item by item into i
|
|
select i).Count() > 1 || RawDefaultValue.Length<250) {
|
|
StringBuilder xSB = new StringBuilder();
|
|
if(IsGlobal) {
|
|
xSB.AppendLine("global " + Name + "\r\n");
|
|
}
|
|
xSB.AppendFormat("{0} db ", Name);
|
|
for (int i = 0; i < (RawDefaultValue.Length - 1); i++) {
|
|
xSB.AppendFormat("{0}, ",
|
|
RawDefaultValue[i]);
|
|
}
|
|
xSB.Append(RawDefaultValue.Last());
|
|
return xSB.ToString();
|
|
} else {
|
|
//aOutputWriter.WriteLine("TIMES 0x50000 db 0");
|
|
return "global " + Name + "\r\n" + Name + ": TIMES " + RawDefaultValue.Count() + " db " + RawDefaultValue[0];
|
|
}
|
|
}
|
|
if (UntypedDefaultValue != null) {
|
|
StringBuilder xSB = new StringBuilder();
|
|
if (IsGlobal) {
|
|
xSB.AppendLine("global " + Name + "\r\n");
|
|
}
|
|
xSB.AppendFormat("{0} dd ", Name);
|
|
Func<object, string> xGetTextForItem = delegate(object aItem) {
|
|
var xElementRef = aItem as ElementReference;
|
|
if (xElementRef == null) {
|
|
return aItem.ToString();
|
|
} else {
|
|
if (xElementRef.Offset == 0) {
|
|
return xElementRef.Name;
|
|
}
|
|
return xElementRef.Name + " + " + xElementRef.Offset;
|
|
}
|
|
};
|
|
for (int i = 0; i < (UntypedDefaultValue.Length - 1); i++) {
|
|
xSB.AppendFormat("{0}, ",
|
|
xGetTextForItem(UntypedDefaultValue[i]));
|
|
}
|
|
xSB.Append(xGetTextForItem(UntypedDefaultValue.Last()));
|
|
return xSB.ToString();
|
|
}
|
|
throw new Exception("Situation unsupported!");
|
|
}
|
|
|
|
public int CompareTo(DataMember other) {
|
|
return String.Compare(Name, other.Name);
|
|
}
|
|
|
|
public bool IsGlobal {
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public override ulong? ActualAddress {
|
|
get {
|
|
// TODO: for now, we dont have any data alignment
|
|
return StartAddress;
|
|
}
|
|
}
|
|
|
|
public override void UpdateAddress(Assembler aAssembler, ref ulong xAddress) {
|
|
if (Alignment > 0) {
|
|
if (xAddress % Alignment != 0) {
|
|
xAddress += Alignment - (xAddress % Alignment);
|
|
}
|
|
}
|
|
base.UpdateAddress(aAssembler, ref xAddress);
|
|
if (RawDefaultValue != null) {
|
|
xAddress += (ulong)RawDefaultValue.LongLength;
|
|
}
|
|
if (UntypedDefaultValue != null) {
|
|
// TODO: what to do with 64bit target platforms? right now we only support 32bit
|
|
xAddress += (ulong)(UntypedDefaultValue.LongLength * 4);
|
|
}
|
|
}
|
|
|
|
public override bool IsComplete(Assembler aAssembler) {
|
|
if (UntypedDefaultValue != null &&
|
|
UntypedDefaultValue.LongLength>0) {
|
|
foreach (var xReference in (from item in UntypedDefaultValue
|
|
let xRef = item as ElementReference
|
|
where xRef != null
|
|
select xRef)) {
|
|
var xRef = aAssembler.TryResolveReference(xReference);
|
|
if (xRef == null) {
|
|
return false;
|
|
} else if (!xRef.IsComplete(aAssembler)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public override byte[] GetData(Assembler aAssembler) {
|
|
if (UntypedDefaultValue != null &&
|
|
UntypedDefaultValue.LongLength > 0) {
|
|
var xBuff = (byte[])Array.CreateInstance(typeof(byte), UntypedDefaultValue.LongLength * 4);
|
|
for (int i = 0; i < UntypedDefaultValue.Length; i++) {
|
|
var xRef = UntypedDefaultValue[i] as ElementReference;
|
|
byte[] xTemp;
|
|
if (xRef != null) {
|
|
var xTheRef = aAssembler.TryResolveReference(xRef);
|
|
if (xTheRef == null) {
|
|
throw new Exception("Reference not found!");
|
|
}
|
|
if (!xTheRef.ActualAddress.HasValue) {
|
|
Console.Write("");
|
|
}
|
|
xTemp = BitConverter.GetBytes(xTheRef.ActualAddress.Value);
|
|
} else {
|
|
if (UntypedDefaultValue[i] is int) {
|
|
xTemp = BitConverter.GetBytes((int)UntypedDefaultValue[i]);
|
|
} else {
|
|
if (UntypedDefaultValue[i] is uint) {
|
|
xTemp = BitConverter.GetBytes((uint)UntypedDefaultValue[i]);
|
|
} else {
|
|
throw new Exception("Invalid value inside UntypedDefaultValue");
|
|
}
|
|
}
|
|
}
|
|
Array.Copy(xTemp, 0, xBuff, i * 4, 4);
|
|
}
|
|
return xBuff;
|
|
}
|
|
return RawDefaultValue;
|
|
}
|
|
|
|
public override void WriteData(Assembler aAssembler, Stream aOutput) {
|
|
if (UntypedDefaultValue != null &&
|
|
UntypedDefaultValue.LongLength > 0) {
|
|
//var xBuff = (byte[])Array.CreateInstance(typeof(byte), UntypedDefaultValue.LongLength * 4);
|
|
for (int i = 0; i < UntypedDefaultValue.Length; i++) {
|
|
var xRef = UntypedDefaultValue[i] as ElementReference;
|
|
//byte[] xTemp;
|
|
if (xRef != null) {
|
|
var xTheRef = aAssembler.TryResolveReference(xRef);
|
|
if (xTheRef == null) {
|
|
throw new Exception("Reference not found!");
|
|
}
|
|
if (!xTheRef.ActualAddress.HasValue) {
|
|
Console.Write("");
|
|
}
|
|
aOutput.Write(BitConverter.GetBytes(xTheRef.ActualAddress.Value), 0, 4);
|
|
//xTemp = BitConverter.GetBytes();
|
|
} else {
|
|
if (UntypedDefaultValue[i] is int) {
|
|
aOutput.Write(BitConverter.GetBytes((int)UntypedDefaultValue[i]), 0, 4);
|
|
//xTemp = BitConverter.GetBytes((int)UntypedDefaultValue[i]);
|
|
} else {
|
|
if (UntypedDefaultValue[i] is uint) {
|
|
aOutput.Write(BitConverter.GetBytes((uint)UntypedDefaultValue[i]), 0, 4);
|
|
|
|
//xTemp = BitConverter.GetBytes((uint)UntypedDefaultValue[i]);
|
|
} else {
|
|
throw new Exception("Invalid value inside UntypedDefaultValue");
|
|
}
|
|
}
|
|
}
|
|
//Array.Copy(xTemp, 0, xBuff, i * 4, 4);
|
|
}
|
|
} else {
|
|
aOutput.Write(RawDefaultValue, 0, RawDefaultValue.Length);
|
|
}
|
|
}
|
|
}
|
|
}
|