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 { 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().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().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 xGetTextForItem = delegate(object aItem) { var xElementRef = aItem as ElementReference; if (xElementRef == null) { return (aItem??0).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); } } } }