示例#1
0
        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);
        }
示例#2
0
        public SPEObjectManager(SPEEmulator.IEndianBitConverter conv)
        {
            this.Converter   = conv;
            this.ObjectTable = ReadObjectTable(conv);

            KnownObjectsById  = new Dictionary <uint, object>();
            KnownObjectsByObj = new Dictionary <object, uint>(new PointerComparer());

            Serializers = GetDefaultSerializers();
        }
示例#3
0
        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);
            }
        }
示例#4
0
        /// <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);
        }
示例#5
0
 public EntryEnumerator(ObjectTableWrapper owner)
 {
     m_owner = owner;
 }