public object ReadObjectFromLS(uint objectIndex, object storage) { if (objectIndex == 0) { return(null); } if (!KnownObjectsById.ContainsKey(objectIndex)) { ObjectTableEntry e = ObjectTable[objectIndex]; Type eltype = FindElementType(objectIndex); ISerializer s; Serializers.TryGetValue(eltype, out s); if (s == null && eltype.IsArray) { Serializers.TryGetValue(typeof(Array), out s); } if (s == null) { throw new Exception("Unable to deserialize element of type: " + eltype.FullName); } SPEEmulator.EndianBitConverter c = new SPEEmulator.EndianBitConverter(new byte[e.AlignedSize]); Converter.ReadBytes(e.Offset, c.Data); object el = s.Deserialize(c, e, storage); KnownObjectsById[objectIndex] = el; KnownObjectsByObj[el] = objectIndex; } return(KnownObjectsById[objectIndex]); }
private static ObjectTableWrapper ReadObjectTable(SPEEmulator.IEndianBitConverter conv) { uint object_table_size = conv.ReadUInt(SPEJITCompiler.OBJECT_TABLE_OFFSET); SPEEmulator.EndianBitConverter obj_tb_tmp = new SPEEmulator.EndianBitConverter(new byte[(object_table_size + 1) * 16]); conv.ReadBytes(SPEJITCompiler.OBJECT_TABLE_OFFSET, obj_tb_tmp.Data); uint[] object_table = new uint[(object_table_size + 1) * 4]; for (int i = 0; i < object_table.Length; i++) { object_table[i] = obj_tb_tmp.ReadUInt(); } ObjectTableWrapper objtable = new ObjectTableWrapper(object_table); /*Console.WriteLine("#Size {0}, nextFree: {1}, nextOffset: {2}, memSize: {3}", objtable.Size, objtable.NextFree, objtable.NextOffset, objtable.Memsize); * foreach (var e in objtable) * Console.WriteLine(e.ToString());*/ foreach (var v in objtable.Where(c => c.KnownType == AccCIL.KnownObjectTypes.String)) { byte[] localdata = new byte[v.AlignedSize]; conv.ReadBytes(v.Offset, localdata); objtable.Strings.Add(System.Text.Encoding.UTF8.GetString(localdata, 0, (int)v.Size), v.Index); } return(objtable); }
public override T Execute <T>(params object[] args) { bool showGui = this.ShowGUI; SPEEmulator.SPEProcessor spe; SPEEmulatorTestApp.Simulator sx = null; if (showGui) { // Run program sx = new SPEEmulatorTestApp.Simulator(new string[] { m_elf }); sx.StartAndPause(); spe = sx.SPE; } else { spe = new SPEEmulator.SPEProcessor(); spe.LoadELF(m_elf); m_workingEvent = new System.Threading.ManualResetEvent(false); } SPEEmulator.EndianBitConverter conv = new SPEEmulator.EndianBitConverter(spe.LS); SPEObjectManager manager = new SPEObjectManager(conv); Dictionary <uint, int> transferedObjects = base.LoadInitialArguments(conv, manager, args); spe.RegisterCallbackHandler(SPEJITCompiler.STOP_METHOD_CALL & 0xff, spe_callback); if (showGui) { System.Windows.Forms.Application.Run(sx); } else { m_exitCode = 0; m_workingEvent.Reset(); spe.SPEStopped += new SPEEmulator.StatusEventDelegate(spe_SPEStopped); spe.Exit += new SPEEmulator.ExitEventDelegate(spe_Exit); spe.Start(); m_workingEvent.WaitOne(); spe.SPEStopped -= new SPEEmulator.StatusEventDelegate(spe_SPEStopped); spe.Exit -= new SPEEmulator.ExitEventDelegate(spe_Exit); Console.WriteLine("Executed {0} instructions while running function {1}", spe.SPU.InstructionsExecuted, m_loadedMethod.DeclaringType.FullName + "::" + m_loadedMethod.Name); if (m_exitCode != SPEJITCompiler.STOP_SUCCESSFULL) { throw new Exception("Invalid exitcode: " + m_exitCode); } } spe.UnregisterCallbackHandler(SPEJITCompiler.STOP_METHOD_CALL & 0xff); return(base.FinalizeAndReturn <T>(conv, manager, transferedObjects, args)); }
private static void WriteObjectTable(SPEEmulator.IEndianBitConverter conv, ObjectTableWrapper objtable) { SPEEmulator.EndianBitConverter obj_tb_tmp = new SPEEmulator.EndianBitConverter(new byte[objtable.Data.Length * 4]); foreach (uint u in objtable.Data) { obj_tb_tmp.WriteUInt(u); } conv.WriteBytes(SPEJITCompiler.OBJECT_TABLE_OFFSET, obj_tb_tmp.Data); foreach (KeyValuePair <string, uint> k in objtable.Strings) { ObjectTableEntry e = objtable[k.Value]; System.Diagnostics.Debug.Assert(e.KnownType == AccCIL.KnownObjectTypes.String); System.Diagnostics.Debug.Assert(e.Size == k.Key.Length); byte[] localdata = new byte[e.AlignedSize]; System.Text.Encoding.UTF8.GetBytes(k.Key, 0, k.Key.Length, localdata, 0); conv.WriteBytes(e.Offset, localdata); } }
/// <summary> /// Emits an instruction stream. /// </summary> /// <param name="outstream">The output stream</param> /// <param name="assemblyOutput">The assembly text output, can be null</param> /// <param name="methods">The compiled methods</param> /// <returns>A lookup table with all method calls</returns> public Dictionary <int, Mono.Cecil.MethodReference> EmitInstructionStream(System.IO.Stream outstream, System.IO.TextWriter assemblyOutput, IEnumerable <ICompiledMethod> _methods, out uint bootloader_offset) { //Prepare the call lookup table Dictionary <int, Mono.Cecil.MethodReference> callpoints = new Dictionary <int, Mono.Cecil.MethodReference>(); //Typecast list List <CompiledMethod> methods = _methods.Select(x => (CompiledMethod)x).ToList(); //Get a list of builtins Dictionary <string, Mono.Cecil.MethodDefinition> builtins = new Dictionary <string, Mono.Cecil.MethodDefinition>(CompiledMethod.m_spe_builtins); //Get list of already compiled builtins IDictionary <string, CompiledMethod> includedBuiltins = methods.Where(x => x.Method.Method.DeclaringType.FullName == "SPEJIT.BuiltInSPEMethods").ToDictionary(x => x.Method.Method.Name); //Add any built-in methods for (int i = 0; i < methods.Count; i++) { foreach (Mono.Cecil.MethodReference mr in methods[i].CalledMethods) { if (mr.DeclaringType.FullName == "SPEJIT.BuiltInSPEMethods" && builtins.ContainsKey(mr.Name) && !includedBuiltins.ContainsKey(mr.Name)) { methods.Add((CompiledMethod)AccCIL.AccCIL.JIT(this, builtins[mr.Name])); builtins.Remove(mr.Name); } } } //The size allocated for bootloader and call handler int BOOTLOADER_LENGTH = BOOT_LOADER.Length + (4 - BOOT_LOADER.Length % 4) % 4; BOOTLOADER_LENGTH += CALL_HANDLER.Length + (4 - CALL_HANDLER.Length % 4) % 4; BOOTLOADER_LENGTH *= 4; //We write in the default size in the ELF, but the actual loader is free to change it ObjectTableWrapper objtable = new ObjectTableWrapper(OBJECT_TABLE_SIZE, 256 * 1024); uint objtableindex = objtable.AddObject(KnownObjectTypes.UInt, (uint)(OBJECT_TABLE_SIZE * 16), null); uint bootloadertableindex = objtable.AddObject(KnownObjectTypes.Bootloader, (uint)BOOTLOADER_LENGTH, null); objtable[objtableindex].Refcount = 1; objtable[bootloadertableindex].Refcount = 1; uint method_object_offset = objtable.NextFree; Dictionary <string, int> stringLiteralCounts = new Dictionary <string, int>(); foreach (CompiledMethod cm in methods) { foreach (string s in cm.StringLiterals) { if (!stringLiteralCounts.ContainsKey(s)) { stringLiteralCounts.Add(s, 0); } stringLiteralCounts[s]++; } } //Register all loaded functions in the object table Dictionary <CompiledMethod, int> methodOffsets = new Dictionary <CompiledMethod, int>(); foreach (CompiledMethod cm in methods) { cm.Prolouge = GenerateProlouge(cm); cm.Epilouge = GenerateEpilouge(cm); uint index = objtable.AddObject(KnownObjectTypes.Code, (uint)cm.TotalSize, null); objtable[index].Refcount = 1; methodOffsets.Add(cm, (int)objtable[index].Offset); } //Register all string literals as objects Dictionary <string, uint> stringLiteralRefs = new Dictionary <string, uint>(); foreach (KeyValuePair <string, int> w in stringLiteralCounts) { uint index = objtable.AddObject(KnownObjectTypes.String, (uint)System.Text.Encoding.UTF8.GetByteCount(w.Key), null); stringLiteralRefs.Add(w.Key, index); //Assign the correct ref count objtable[index].Refcount = (uint)stringLiteralCounts[w.Key]; } //Patch all code object types to have a string reference foreach (CompiledMethod cm in methods) { uint index = (uint)(methods.IndexOf(cm) + method_object_offset); System.Diagnostics.Debug.Assert(objtable[index].KnownType == KnownObjectTypes.Code); objtable[index].Type = stringLiteralRefs[cm.Fullname]; } //Write a placeholder for the startup arguments byte[] zeroentry = new byte[16]; outstream.Write(zeroentry, 0, 16); SPEEmulator.EndianBitConverter c = new SPEEmulator.EndianBitConverter(new byte[objtable.Data.Length * 4]); foreach (var u in objtable.Data) { c.WriteUInt(u); } outstream.Write(c.Data, 0, c.Data.Length); if (assemblyOutput != null) { assemblyOutput.WriteLine("### Object table ###"); assemblyOutput.WriteLine("#Size {0}, nextFree: {1}, nextOffset: {2}, memSize: {3}", objtable.Size, objtable.NextFree, objtable.NextOffset, objtable.Memsize); foreach (var e in objtable) { assemblyOutput.WriteLine(e.ToString()); } } bootloader_offset = (uint)outstream.Length; if (assemblyOutput != null) { assemblyOutput.WriteLine("# Bootloader"); } //Flush loader code InstructionsToBytes(BOOT_LOADER, outstream, assemblyOutput, null); outstream.Write(zeroentry, 0, (16 - (BOOT_LOADER.Length * 4) % 16) % 16); int callhandlerOffset = (int)outstream.Length / 4; if (assemblyOutput != null) { assemblyOutput.WriteLine("# Callhandler"); } //Flush loader code InstructionsToBytes(CALL_HANDLER, outstream, assemblyOutput, null); outstream.Write(zeroentry, 0, (16 - (CALL_HANDLER.Length * 4) % 16) % 16); //Create a fast lookup table Dictionary <Mono.Cecil.MethodReference, int> methodOffsetLookup = methodOffsets.ToDictionary(x => (Mono.Cecil.MethodReference)x.Key.Method.Method, x => x.Value / 4); //We know the layout of each method, we can patch the call instructions foreach (CompiledMethod cm in methods) { List <string> constants = cm.Constants.Distinct().ToList(); Dictionary <string, int> offsets = new Dictionary <string, int>(); uint index = (uint)methods.IndexOf(cm) + method_object_offset; System.Diagnostics.Debug.Assert(objtable[index].KnownType == KnownObjectTypes.Code); System.Diagnostics.Debug.Assert(objtable[index].Offset == (uint)outstream.Length); System.Diagnostics.Debug.Assert(objtable[index].Type == stringLiteralRefs[cm.Fullname]); int constantOffsets = (cm.Instructions.Count + cm.Epilouge.Count) + (4 - (cm.Instructions.Count + cm.Prolouge.Count + cm.Epilouge.Count) % 4) % 4; for (int i = 0; i < constants.Count; i++) { offsets.Add(constants[i], i * 4 + constantOffsets); } if (assemblyOutput != null) { assemblyOutput.WriteLine("###########################################"); assemblyOutput.WriteLine("# Begin Function: " + cm.Method.Method.Name); assemblyOutput.WriteLine("###########################################"); assemblyOutput.WriteLine(); } cm.PatchBranches(); cm.PatchCalls(methodOffsetLookup, callhandlerOffset, callpoints); cm.PatchConstants(offsets); cm.PatchStringLoads(stringLiteralRefs); int offset = (cm.Prolouge.Count + cm.Instructions.Count + cm.Epilouge.Count) * 4; if (assemblyOutput != null) { assemblyOutput.WriteLine("### Prolouge Begin ###"); } InstructionsToBytes(cm.Prolouge, outstream, assemblyOutput, null); if (assemblyOutput != null) { assemblyOutput.WriteLine("### Prolouge End ###"); } #if DEBUG long streamOffset = outstream.Position / 4; Dictionary <long, List <Mono.Cecil.Cil.Instruction> > instructionLookup = new Dictionary <long, List <Mono.Cecil.Cil.Instruction> >(); foreach (KeyValuePair <Mono.Cecil.Cil.Instruction, int> x in cm.InstructionOffsets) { List <Mono.Cecil.Cil.Instruction> ix; instructionLookup.TryGetValue(x.Value + streamOffset, out ix); if (ix == null) { instructionLookup.Add(x.Value + streamOffset, ix = new List <Mono.Cecil.Cil.Instruction>()); } ix.Add(x.Key); } #else Dictionary <long, List <Mono.Cecil.Cil.Instruction> > instructionLookup = null; #endif InstructionsToBytes(cm.Instructions, outstream, assemblyOutput, instructionLookup); if (assemblyOutput != null) { assemblyOutput.WriteLine("### Epilouge Begin ###"); } InstructionsToBytes(cm.Epilouge, outstream, assemblyOutput, null); if (assemblyOutput != null) { assemblyOutput.WriteLine("### Epilouge End ###"); } outstream.Write(zeroentry, 0, (16 - offset % 16) % 16); foreach (string s in constants) { ulong high = ulong.Parse(s.Substring(0, 16), System.Globalization.NumberStyles.HexNumber); ulong low = ulong.Parse(s.Substring(16), System.Globalization.NumberStyles.HexNumber); outstream.Write(ReverseEndian(BitConverter.GetBytes(high)), 0, 8); outstream.Write(ReverseEndian(BitConverter.GetBytes(low)), 0, 8); if (assemblyOutput != null) { assemblyOutput.WriteLine("Constant: " + s); } } System.Diagnostics.Debug.Assert(objtable[index].Size + objtable[index].Offset == (uint)outstream.Length); if (assemblyOutput != null) { assemblyOutput.WriteLine(); assemblyOutput.WriteLine(); } } if (assemblyOutput != null) { assemblyOutput.WriteLine("# String literals"); } foreach (KeyValuePair <string, uint> w in stringLiteralRefs) { System.Diagnostics.Debug.Assert(objtable[w.Value].KnownType == KnownObjectTypes.String); System.Diagnostics.Debug.Assert(objtable[w.Value].Offset == (uint)outstream.Length); byte[] data = System.Text.Encoding.UTF8.GetBytes(w.Key); System.Diagnostics.Debug.Assert(objtable[w.Value].Size == (uint)data.Length); outstream.Write(data, 0, data.Length); outstream.Write(zeroentry, 0, (16 - data.Length % 16) % 16); if (assemblyOutput != null) { assemblyOutput.WriteLine("0x{0:x4}: \"{1}\" -> {2}", objtable[w.Value].Offset, w.Key, w.Value); } } return(callpoints); }
public byte[] Serialize(object element, out uint size) { if (element == null) { throw new ArgumentNullException("element"); } Array arr = (Array)element; Type eltype = element.GetType().GetElementType(); AccCIL.KnownObjectTypes objt; uint elsize; string typename; if (eltype.IsPrimitive) { objt = AccCIL.AccCIL.GetObjType(eltype); elsize = 1u << (int)BuiltInSPEMethods.get_array_elem_len_mult((uint)objt); typename = null; } else { elsize = 4; objt = AccCIL.KnownObjectTypes.Object; typename = element.GetType().FullName; } size = (uint)arr.Length * elsize; uint alignedSize = ((size + 15) >> 4) << 4; SPEEmulator.EndianBitConverter c = new SPEEmulator.EndianBitConverter(new byte[alignedSize]); if (eltype.IsPrimitive) { ISerializer elserializer; m_parent.Serializers.TryGetValue(eltype, out elserializer); if (elserializer == null) { throw new Exception("Unsupported inner type: " + eltype.FullName); } for (int i = 0; i < arr.Length; i++) { //TODO: This is inefficient, it should write directly into the target buffer uint s; byte[] localdata = elserializer.Serialize(arr.GetValue(i), out s); Array.Copy(localdata, 0, c.Data, c.Position, localdata.Length); c.Position += s; } } else { for (int i = 0; i < arr.Length; i++) { object value = arr.GetValue(i); if (value == null) { c.WriteUInt(0); } else { //If we are writing back the array, write back the element as well if (m_parent.KnownObjectsByObj.ContainsKey(element) && m_parent.KnownObjectsByObj.ContainsKey(value)) { m_parent.WriteObjectToLS(m_parent.KnownObjectsByObj[value], value); } else { c.WriteUInt(m_parent.CreateObjectOnLS(value)); } } } } return(c.Data); }
/// <summary> /// Emits an instruction stream. /// </summary> /// <param name="outstream">The output stream</param> /// <param name="assemblyOutput">The assembly text output, can be null</param> /// <param name="methods">The compiled methods</param> /// <returns>A lookup table with all method calls</returns> public Dictionary<int, Mono.Cecil.MethodReference> EmitInstructionStream(System.IO.Stream outstream, System.IO.TextWriter assemblyOutput, IEnumerable<ICompiledMethod> _methods, out uint bootloader_offset) { //Prepare the call lookup table Dictionary<int, Mono.Cecil.MethodReference> callpoints = new Dictionary<int, Mono.Cecil.MethodReference>(); //Typecast list List<CompiledMethod> methods = _methods.Select(x => (CompiledMethod)x).ToList(); //Get a list of builtins Dictionary<string, Mono.Cecil.MethodDefinition> builtins = new Dictionary<string, Mono.Cecil.MethodDefinition>(CompiledMethod.m_spe_builtins); //Get list of already compiled builtins IDictionary<string, CompiledMethod> includedBuiltins = methods.Where(x => x.Method.Method.DeclaringType.FullName == "SPEJIT.BuiltInSPEMethods").ToDictionary(x => x.Method.Method.Name); //Add any built-in methods for(int i = 0; i < methods.Count; i++) foreach (Mono.Cecil.MethodReference mr in methods[i].CalledMethods) if (mr.DeclaringType.FullName == "SPEJIT.BuiltInSPEMethods" && builtins.ContainsKey(mr.Name) && !includedBuiltins.ContainsKey(mr.Name)) { methods.Add((CompiledMethod)AccCIL.AccCIL.JIT(this, builtins[mr.Name])); builtins.Remove(mr.Name); } //The size allocated for bootloader and call handler int BOOTLOADER_LENGTH = BOOT_LOADER.Length + (4 - BOOT_LOADER.Length % 4) % 4; BOOTLOADER_LENGTH += CALL_HANDLER.Length + (4 - CALL_HANDLER.Length % 4) % 4; BOOTLOADER_LENGTH *= 4; //We write in the default size in the ELF, but the actual loader is free to change it ObjectTableWrapper objtable = new ObjectTableWrapper(OBJECT_TABLE_SIZE, 256 * 1024); uint objtableindex = objtable.AddObject(KnownObjectTypes.UInt, (uint)(OBJECT_TABLE_SIZE * 16), null); uint bootloadertableindex = objtable.AddObject(KnownObjectTypes.Bootloader, (uint)BOOTLOADER_LENGTH, null); objtable[objtableindex].Refcount = 1; objtable[bootloadertableindex].Refcount = 1; uint method_object_offset = objtable.NextFree; Dictionary<string, int> stringLiteralCounts = new Dictionary<string, int>(); foreach (CompiledMethod cm in methods) foreach (string s in cm.StringLiterals) { if (!stringLiteralCounts.ContainsKey(s)) stringLiteralCounts.Add(s, 0); stringLiteralCounts[s]++; } //Register all loaded functions in the object table Dictionary<CompiledMethod, int> methodOffsets = new Dictionary<CompiledMethod,int>(); foreach(CompiledMethod cm in methods) { cm.Prolouge = GenerateProlouge(cm); cm.Epilouge = GenerateEpilouge(cm); uint index = objtable.AddObject(KnownObjectTypes.Code, (uint)cm.TotalSize, null); objtable[index].Refcount = 1; methodOffsets.Add(cm, (int)objtable[index].Offset); } //Register all string literals as objects Dictionary<string, uint> stringLiteralRefs = new Dictionary<string, uint>(); foreach (KeyValuePair<string, int> w in stringLiteralCounts) { uint index = objtable.AddObject(KnownObjectTypes.String, (uint)System.Text.Encoding.UTF8.GetByteCount(w.Key), null); stringLiteralRefs.Add(w.Key, index); //Assign the correct ref count objtable[index].Refcount = (uint)stringLiteralCounts[w.Key]; } //Patch all code object types to have a string reference foreach (CompiledMethod cm in methods) { uint index = (uint)(methods.IndexOf(cm) + method_object_offset); System.Diagnostics.Debug.Assert(objtable[index].KnownType == KnownObjectTypes.Code); objtable[index].Type = stringLiteralRefs[cm.Fullname]; } //Write a placeholder for the startup arguments byte[] zeroentry = new byte[16]; outstream.Write(zeroentry, 0, 16); SPEEmulator.EndianBitConverter c = new SPEEmulator.EndianBitConverter(new byte[objtable.Data.Length * 4]); foreach (var u in objtable.Data) c.WriteUInt(u); outstream.Write(c.Data, 0, c.Data.Length); if (assemblyOutput != null) { assemblyOutput.WriteLine("### Object table ###"); assemblyOutput.WriteLine("#Size {0}, nextFree: {1}, nextOffset: {2}, memSize: {3}", objtable.Size, objtable.NextFree, objtable.NextOffset, objtable.Memsize); foreach (var e in objtable) assemblyOutput.WriteLine(e.ToString()); } bootloader_offset = (uint)outstream.Length; if (assemblyOutput != null) assemblyOutput.WriteLine("# Bootloader"); //Flush loader code InstructionsToBytes(BOOT_LOADER, outstream, assemblyOutput, null); outstream.Write(zeroentry, 0, (16 - (BOOT_LOADER.Length * 4) % 16) % 16); int callhandlerOffset = (int)outstream.Length / 4; if (assemblyOutput != null) assemblyOutput.WriteLine("# Callhandler"); //Flush loader code InstructionsToBytes(CALL_HANDLER, outstream, assemblyOutput, null); outstream.Write(zeroentry, 0, (16 - (CALL_HANDLER.Length * 4) % 16) % 16); //Create a fast lookup table Dictionary<Mono.Cecil.MethodReference, int> methodOffsetLookup = methodOffsets.ToDictionary(x => (Mono.Cecil.MethodReference)x.Key.Method.Method, x => x.Value / 4); //We know the layout of each method, we can patch the call instructions foreach (CompiledMethod cm in methods) { List<string> constants = cm.Constants.Distinct().ToList(); Dictionary<string, int> offsets = new Dictionary<string, int>(); uint index = (uint)methods.IndexOf(cm) + method_object_offset; System.Diagnostics.Debug.Assert(objtable[index].KnownType == KnownObjectTypes.Code); System.Diagnostics.Debug.Assert(objtable[index].Offset == (uint)outstream.Length); System.Diagnostics.Debug.Assert(objtable[index].Type == stringLiteralRefs[cm.Fullname]); int constantOffsets = (cm.Instructions.Count + cm.Epilouge.Count) + (4 - (cm.Instructions.Count + cm.Prolouge.Count + cm.Epilouge.Count) % 4) % 4; for(int i = 0; i < constants.Count; i++) offsets.Add(constants[i], i * 4 + constantOffsets); if (assemblyOutput != null) { assemblyOutput.WriteLine("###########################################"); assemblyOutput.WriteLine("# Begin Function: " + cm.Method.Method.Name); assemblyOutput.WriteLine("###########################################"); assemblyOutput.WriteLine(); } cm.PatchBranches(); cm.PatchCalls(methodOffsetLookup, callhandlerOffset, callpoints); cm.PatchConstants(offsets); cm.PatchStringLoads(stringLiteralRefs); int offset = (cm.Prolouge.Count + cm.Instructions.Count + cm.Epilouge.Count) * 4; if (assemblyOutput != null) assemblyOutput.WriteLine("### Prolouge Begin ###"); InstructionsToBytes(cm.Prolouge, outstream, assemblyOutput, null); if (assemblyOutput != null) assemblyOutput.WriteLine("### Prolouge End ###"); #if DEBUG long streamOffset = outstream.Position / 4; Dictionary<long, List<Mono.Cecil.Cil.Instruction>> instructionLookup = new Dictionary<long, List<Mono.Cecil.Cil.Instruction>>(); foreach (KeyValuePair<Mono.Cecil.Cil.Instruction, int> x in cm.InstructionOffsets) { List<Mono.Cecil.Cil.Instruction> ix; instructionLookup.TryGetValue(x.Value + streamOffset, out ix); if (ix == null) instructionLookup.Add(x.Value + streamOffset, ix = new List<Mono.Cecil.Cil.Instruction>()); ix.Add(x.Key); } #else Dictionary<long, List<Mono.Cecil.Cil.Instruction>> instructionLookup = null; #endif InstructionsToBytes(cm.Instructions, outstream, assemblyOutput, instructionLookup); if (assemblyOutput != null) assemblyOutput.WriteLine("### Epilouge Begin ###"); InstructionsToBytes(cm.Epilouge, outstream, assemblyOutput, null); if (assemblyOutput != null) assemblyOutput.WriteLine("### Epilouge End ###"); outstream.Write(zeroentry, 0, (16 - offset % 16) % 16); foreach (string s in constants) { ulong high = ulong.Parse(s.Substring(0, 16), System.Globalization.NumberStyles.HexNumber); ulong low = ulong.Parse(s.Substring(16), System.Globalization.NumberStyles.HexNumber); outstream.Write(ReverseEndian(BitConverter.GetBytes(high)), 0, 8); outstream.Write(ReverseEndian(BitConverter.GetBytes(low)), 0, 8); if (assemblyOutput != null) assemblyOutput.WriteLine("Constant: " + s); } System.Diagnostics.Debug.Assert(objtable[index].Size + objtable[index].Offset == (uint)outstream.Length); if (assemblyOutput != null) { assemblyOutput.WriteLine(); assemblyOutput.WriteLine(); } } if (assemblyOutput != null) assemblyOutput.WriteLine("# String literals"); foreach (KeyValuePair<string, uint> w in stringLiteralRefs) { System.Diagnostics.Debug.Assert(objtable[w.Value].KnownType == KnownObjectTypes.String); System.Diagnostics.Debug.Assert(objtable[w.Value].Offset == (uint)outstream.Length); byte[] data = System.Text.Encoding.UTF8.GetBytes(w.Key); System.Diagnostics.Debug.Assert(objtable[w.Value].Size == (uint)data.Length); outstream.Write(data, 0, data.Length); outstream.Write(zeroentry, 0, (16 - data.Length % 16) % 16); if (assemblyOutput != null) assemblyOutput.WriteLine("0x{0:x4}: \"{1}\" -> {2}", objtable[w.Value].Offset, w.Key, w.Value); } return callpoints; }