Пример #1
0
        public static bool CreateDelegate(metadata.TypeSpec ts,
                                          target.Target t, TysilaState s)
        {
            if (delegate_m_target == null)
            {
                delegate_m_target = ts.m.GetFieldDefRow("m_target", ts.m.SystemDelegate);
                if (delegate_m_target == null)
                {
                    delegate_m_target = ts.m.GetFieldDefRow("_target", ts.m.SystemDelegate);
                }
                delegate_method_ptr = ts.m.GetFieldDefRow("method_ptr", ts.m.SystemDelegate);
                if (delegate_method_ptr == null)
                {
                    delegate_method_ptr = ts.m.GetFieldDefRow("_methodPtr", ts.m.SystemDelegate);
                }
            }

            // Generate required delegate methods in IR
            CreateDelegateCtor(ts, t, s);
            CreateDelegateInvoke(ts, t, s);
            CreateDelegateBeginInvoke(ts, t, s);
            CreateDelegateEndInvoke(ts, t, s);


            return(true);
        }
Пример #2
0
        private static void CreateDelegateCtor(TypeSpec ts, Target t, TysilaState s)
        {
            var ms = ts.m.GetMethodSpec(ts, ".ctor", 0, null);

            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            List <cil.CilNode.IRNode> ret = new List <cil.CilNode.IRNode>();

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>(0);
            TypeSpec fld_ts;

            // Enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // Store m_target
            stack_before = ConvertToIR.ldarg(n, c, stack_before, 0);
            stack_before = ConvertToIR.ldarg(n, c, stack_before, 1);
            stack_before = ConvertToIR.ldflda(n, c, stack_before, false, out fld_ts, 1, delegate_m_target);
            stack_before = ConvertToIR.binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr, 2);
            stack_before = ConvertToIR.stind(n, c, stack_before, c.t.GetSize(fld_ts), 1, 0);
            stack_before.Pop();

            // Store method_ptr
            stack_before = ConvertToIR.ldarg(n, c, stack_before, 0);
            stack_before = ConvertToIR.ldarg(n, c, stack_before, 2);
            stack_before = ConvertToIR.ldflda(n, c, stack_before, false, out fld_ts, 1, delegate_method_ptr);
            stack_before = ConvertToIR.binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr, 2);
            stack_before = ConvertToIR.stind(n, c, stack_before, c.t.GetSize(fld_ts), 1, 0);
            stack_before.Pop();

            // Ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, stack_before = stack_before, stack_after = stack_before
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            var msc = new layout.Layout.MethodSpecWithEhdr
            {
                ms = ms,
                c  = c
            };

            s.r.MethodRequestor.Remove(msc);
            s.r.MethodRequestor.Request(msc);
        }
Пример #3
0
        protected internal override Code AssembleBoxedMethod(MethodSpec ms, TysilaState s)
        {
            /* To unbox, we simply add the size of system.object to
             * first argument, then jmp to the actual method
             */

            var c = new Code();

            c.mc = new List <MCInst>();
            c.s  = s;

            var this_reg = psize == 4 ? new ContentsReg {
                basereg = r_ebp, disp = 8, size = 4
            } : x86_64.x86_64_Assembler.r_rdi;
            var sysobjsize = layout.Layout.GetTypeSize(ms.m.SystemObject, this);

            c.mc.Add(inst(psize == 4 ? x86_add_rm32_imm8 : x86_add_rm64_imm8, this_reg, sysobjsize, null));

            var unboxed  = ms.Unbox;
            var act_meth = unboxed.MangleMethod();

            c.s.r.MethodRequestor.Request(unboxed);


            c.mc.Add(inst(x86_jmp_rel32, new Param {
                t = Opcode.vl_str, str = act_meth
            }, null));

            return(c);
        }
Пример #4
0
        private static void AddBaseType(IList <byte> d, TypeSpec ts, IBinaryFile of, ISection os, ref ulong offset, Target t,
                                        TysilaState s)
        {
            if (ts.other != null && ts.stype != TypeSpec.SpecialType.Boxed)
            {
                var bt = ts.other.Box;

                var ext_reloc = of.CreateRelocation();
                ext_reloc.Addend    = 0;
                ext_reloc.DefinedIn = os;
                ext_reloc.Offset    = offset;
                ext_reloc.Type      = t.GetDataToDataReloc();

                var ext_sym = of.CreateSymbol();
                ext_sym.Name = bt.MangleType();

                ext_reloc.References = ext_sym;
                of.AddRelocation(ext_reloc);

                s.r.VTableRequestor.Request(bt);
            }
            for (int i = 0; i < t.GetPointerSize(); i++, offset++)
            {
                d.Add(0);
            }
        }
Пример #5
0
        private static void CreateDelegateEndInvoke(TypeSpec ts, Target t, TysilaState s)
        {
            var ms = ts.m.GetMethodSpec(ts, "EndInvoke", 0, null);

            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            List <cil.CilNode.IRNode> ret = new List <cil.CilNode.IRNode>();

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>();

            // Enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // Error message
            stack_before = ConvertToIR.ldstr(n, c, stack_before, "BeginInvoke is currently implemented");

            // Create NotImplementedException
            var ni_ts       = c.ms.m.al.GetAssembly("mscorlib").GetTypeSpec("System", "NotImplementedException");
            var ni_ctor_row = ni_ts.m.GetMethodDefRow(ni_ts, ".ctor",
                                                      c.special_meths.inst_Rv_s, c.special_meths);
            var ni_ctor_ms = new MethodSpec
            {
                m     = ni_ts.m,
                type  = ni_ts,
                mdrow = ni_ctor_row,
                msig  = (int)ni_ts.m.GetIntEntry(MetadataStream.tid_MethodDef, ni_ctor_row, 4),
            };

            stack_before = ConvertToIR.newobj(n, c, stack_before, ni_ctor_ms);
            stack_before = ConvertToIR.throw_(n, c, stack_before);

            // Ret - not reached
            //n.irnodes.Add(new cil.CilNode.IRNode { parent = n, opcode = Opcode.oc_ret, ct = ((ret_ts == null) ? ir.Opcode.ct_unknown : Opcode.GetCTFromType(ret_ts)), stack_before = stack_before, stack_after = stack_before });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            var msc = new layout.Layout.MethodSpecWithEhdr
            {
                ms = ms,
                c  = c
            };

            s.r.MethodRequestor.Remove(msc);
            s.r.MethodRequestor.Request(msc);
        }
Пример #6
0
        internal static Code CreateVectorCopyTo(MethodSpec ms,
                                                Target t, TysilaState s)
        {
            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>();

            // enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // We call a libsupcs method here that expects arguments in the order
            //  srcInnerArr, dstArr, startIndex (in dstArr), count
            var stack_after = ldarg(n, c, stack_before, 0);

            stack_after = ldc(n, c, stack_after, layout.Layout.GetArrayFieldOffset(layout.Layout.ArrayField.DataArrayPointer, c.t));
            stack_after = binnumop(n, c, stack_after, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_after = ldind(n, c, stack_after, ms.m.SystemIntPtr);
            stack_after = ldarg(n, c, stack_after, 1);
            stack_after = ldarg(n, c, stack_after, 2);
            stack_after = ldarg(n, c, stack_after, 0);
            stack_after = ldlen(n, c, stack_after);
            //stack_after = ldarg(n, c, stack_after, 2);
            //stack_after = binnumop(n, c, stack_after, cil.Opcode.SingleOpcodes.sub, Opcode.ct_int32);

            //stack_after = debugger_Break(n, c, stack_after);

            stack_after = call(n, c, stack_after, false,
                               "_ZW34System#2ERuntime#2EInteropServices7Marshal_13CopyToManaged_Rv_P4u1Iu1Oii",
                               c.special_meths, c.special_meths.array_copyToManaged);

            // ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ir.Opcode.ct_unknown, stack_before = stack_after, stack_after = stack_after
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            return(c);
        }
Пример #7
0
        internal static Code CreateArraySet(MethodSpec ms,
                                            Target t, TysilaState s)
        {
            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>(0);

            // Returns void
            c.ret_ts = ms.m.SystemVoid;

            // Get array item type
            var given_type = c.la_types[c.la_types.Length - 1];

            if (!given_type.Equals(ms.type.other))
            {
                throw new Exception("Array Set given type not the same as element type");
            }

            // Enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // Get offset to the data item
            stack_before = ArrayGetDataItemPtr(n, c, stack_before, ms);

            // Load given value and store to the address
            stack_before = ldarg(n, c, stack_before, c.la_types.Length - 1);
            stack_before = stind(n, c, stack_before, t.GetSize(given_type));

            // Ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ir.Opcode.ct_unknown, stack_before = stack_before, stack_after = stack_before
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            return(c);
        }
Пример #8
0
        internal static Code CreateArrayGet(MethodSpec ms,
                                            Target t, TysilaState s)
        {
            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>(0);

            // Get return type
            var sig_idx = ms.m.GetMethodDefSigRetTypeIndex(ms.msig);
            var ret_ts  = ms.m.GetTypeSpec(ref sig_idx, ms.gtparams, ms.gmparams);

            c.ret_ts = ret_ts;

            if (!ret_ts.Equals(ms.type.other))
            {
                throw new Exception("Array Get return type not the same as element type");
            }

            // Enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // Get offset to the data item
            stack_before = ArrayGetDataItemPtr(n, c, stack_before, ms);

            // Load it
            stack_before = ldind(n, c, stack_before, ret_ts);

            // Ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ((ret_ts == null) ? ir.Opcode.ct_unknown : Opcode.GetCTFromType(ret_ts)), stack_before = stack_before, stack_after = stack_before
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            return(c);
        }
Пример #9
0
        /*internal static Code CreateVectorGetEnumerator(MethodSpec ms,
         *  Target t)
         * {
         *  Code c = new Code { t = t, ms = ms, s = s };
         *  t.AllocateLocalVarsArgs(c);
         *  cil.CilNode n = new cil.CilNode(ms, 0);
         *
         *  util.Stack<StackItem> stack_before = new util.Stack<StackItem>();
         *
         *  // enter
         *  n.irnodes.Add(new cil.CilNode.IRNode { parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before });
         *
         *
         * }
         */

        internal static Code CreateVectorget_Item(MethodSpec ms,
                                                  Target t, TysilaState s)
        {
            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>();

            // enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // Get return type
            var sig_idx = ms.m.GetMethodDefSigRetTypeIndex(ms.msig);
            var ret_ts  = ms.m.GetTypeSpec(ref sig_idx, ms.gtparams, ms.gmparams);

            c.ret_ts = ret_ts;

            // implement with ldelem
            var stack_after = ldarg(n, c, stack_before, 0);

            stack_after = ldarg(n, c, stack_after, 1);
            stack_after = ldelem(n, c, stack_after, ms.type.other);

            // ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ir.Opcode.ct_unknown, stack_before = stack_before, stack_after = stack_before
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            return(c);
        }
Пример #10
0
        internal static Code CreateVectorget_Count(MethodSpec ms,
                                                   Target t, TysilaState s)
        {
            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>();

            // enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // ldarg, ldlen
            var stack_after = ldarg(n, c, stack_before, 0);

            stack_after = ldlen(n, c, stack_after);

            // ret
            var stack_after2 = new util.Stack <StackItem>(stack_after);

            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ir.Opcode.ct_int32, stack_before = stack_after, stack_after = stack_after2
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            return(c);
        }
Пример #11
0
        private static void OutputVirtualMethods(TypeSpec decl_ts,
                                                 IBinaryFile of, ISection os,
                                                 IList <byte> d, ref ulong offset, target.Target t,
                                                 TysilaState s)
        {
            var vmeths = GetVirtualMethodDeclarations(decl_ts);

            ImplementVirtualMethods(decl_ts, vmeths);

            foreach (var vmeth in vmeths)
            {
                var    impl_ms     = vmeth.impl_meth;
                string impl_target = (impl_ms == null) ? "__cxa_pure_virtual" : impl_ms.MethodReferenceAlias;

                var impl_sym = of.CreateSymbol();
                impl_sym.Name       = impl_target;
                impl_sym.ObjectType = SymbolObjectType.Function;

                var impl_reloc = of.CreateRelocation();
                impl_reloc.Addend     = 0;
                impl_reloc.DefinedIn  = os;
                impl_reloc.Offset     = offset;
                impl_reloc.References = impl_sym;
                impl_reloc.Type       = t.GetDataToCodeReloc();
                of.AddRelocation(impl_reloc);

                for (int i = 0; i < t.GetPointerSize(); i++, offset++)
                {
                    d.Add(0);
                }

                if (impl_ms != null)
                {
                    s.r.MethodRequestor.Request(impl_ms);
                }
            }
        }
Пример #12
0
        internal static Code CreateVectorUnimplemented(MethodSpec ms,
                                                       Target t, TysilaState s)
        {
            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>();

            // Get return type
            var sig_idx = ms.m.GetMethodDefSigRetTypeIndex(ms.msig);
            var ret_ts  = ms.m.GetTypeSpec(ref sig_idx, ms.gtparams, ms.gmparams);

            c.ret_ts = ret_ts;

            // enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // break
            var stack_after = debugger_Break(n, c, stack_before);

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            return(c);
        }
Пример #13
0
        public static void OutputEHdr(MethodSpecWithEhdr ms,
                                      Target t, binary_library.IBinaryFile of,
                                      TysilaState s,
                                      MetadataStream base_m      = null,
                                      binary_library.ISection os = null)
        {
            // Don't compile if not for this architecture
            if (!t.IsMethodValid(ms.ms))
            {
                return;
            }

            if (os == null)
            {
                os = of.GetRDataSection();
            }
            os.Align(t.GetPointerSize());
            var d = os.Data;

            /* Symbol */
            var sym = of.CreateSymbol();

            sym.Name       = ms.ms.MangleMethod() + "EH";
            sym.ObjectType = binary_library.SymbolObjectType.Object;
            sym.Offset     = (ulong)d.Count;
            sym.Type       = binary_library.SymbolType.Global;
            os.AddSymbol(sym);

            if (base_m != null && ms.ms.m != base_m)
            {
                sym.Type = binary_library.SymbolType.Weak;
            }

            foreach (var ehdr in ms.c.ehdrs)
            {
                var v = t.IntPtrArray(BitConverter.GetBytes((int)ehdr.EType));
                foreach (var b in v)
                {
                    d.Add(b);
                }

                /* Handler */
                var hand_sym = of.CreateSymbol();
                hand_sym.Name = ms.ms.MangleMethod() + "EH" + ehdr.EhdrIdx.ToString();

                var hand_reloc = of.CreateRelocation();
                hand_reloc.Addend     = 0;
                hand_reloc.DefinedIn  = os;
                hand_reloc.Offset     = (ulong)d.Count;
                hand_reloc.References = hand_sym;
                hand_reloc.Type       = t.GetDataToCodeReloc();
                of.AddRelocation(hand_reloc);

                for (int i = 0; i < t.GetPointerSize(); i++)
                {
                    d.Add(0);
                }

                /* Catch object */
                if (ehdr.ClassToken != null)
                {
                    var catch_sym = of.CreateSymbol();
                    catch_sym.Name = ehdr.ClassToken.MangleType();

                    var catch_reloc = of.CreateRelocation();
                    catch_reloc.Addend     = 0;
                    catch_reloc.DefinedIn  = os;
                    catch_reloc.Offset     = (ulong)d.Count;
                    catch_reloc.References = catch_sym;
                    catch_reloc.Type       = t.GetDataToDataReloc();
                    of.AddRelocation(catch_reloc);

                    s.r.VTableRequestor.Request(ehdr.ClassToken);
                }
                else if (ehdr.EType == ExceptionHeader.ExceptionHeaderType.Filter)
                {
                    var filt_sym = of.CreateSymbol();
                    filt_sym.Name = ms.ms.MangleMethod() + "EHF" + ehdr.EhdrIdx.ToString();

                    var filt_reloc = of.CreateRelocation();
                    filt_reloc.Addend     = 0;
                    filt_reloc.DefinedIn  = os;
                    filt_reloc.Offset     = (ulong)d.Count;
                    filt_reloc.References = filt_sym;
                    filt_reloc.Type       = t.GetDataToCodeReloc();
                    of.AddRelocation(filt_reloc);
                }
                for (int i = 0; i < t.GetPointerSize(); i++)
                {
                    d.Add(0);
                }
            }

            sym.Size = (long)((ulong)d.Count - sym.Offset);
        }
Пример #14
0
        /* Vtable:
         *
         *  TIPtr (just to a glorified TypeSpec)
         *  IFacePtr (to list of implemented interfaces)
         *  Extends (to base classes for quick castclassex)
         *  TypeSize (to allow MemberwiseClone to work without full Reflection)
         *  Any target-specific data
         *  Method 0
         *  ...
         *
         *  IFaceList TODO
         *
         *
         */

        public static void OutputVTable(TypeSpec ts,
                                        target.Target t, binary_library.IBinaryFile of,
                                        TysilaState s,
                                        MetadataStream base_m = null,
                                        ISection os           = null,
                                        ISection data_sect    = null)
        {
            // Don't compile if not for this architecture
            if (!t.IsTypeValid(ts))
            {
                return;
            }

            /* New signature table */
            s.sigt = new SignatureTable(ts.MangleType());

            // If its a delegate type we also need to output its methods
            if (ts.IsDelegate && !ts.IsGenericTemplate)
            {
                s.r.DelegateRequestor.Request(ts);
            }

            if (os == null)
            {
                os = of.GetRDataSection();
            }
            var d        = os.Data;
            var ptr_size = t.GetCTSize(ir.Opcode.ct_object);

            os.Align(ptr_size);

            ulong offset = (ulong)os.Data.Count;

            /* Symbol */
            var sym = of.CreateSymbol();

            sym.Name       = ts.MangleType();
            sym.ObjectType = binary_library.SymbolObjectType.Object;
            sym.Offset     = offset;
            sym.Type       = binary_library.SymbolType.Global;
            os.AddSymbol(sym);

            if (base_m != null && ts.m != base_m)
            {
                sym.Type = SymbolType.Weak;
            }

            /* TIPtr */
            var tiptr_offset = s.sigt.GetSignatureAddress(ts.Signature, t, s);

            var ti_reloc = of.CreateRelocation();

            ti_reloc.Addend          = tiptr_offset;
            ti_reloc.DefinedIn       = os;
            ti_reloc.Offset          = offset;
            ti_reloc.Type            = t.GetDataToDataReloc();
            ti_reloc.References      = of.CreateSymbol();
            ti_reloc.References.Name = s.sigt.GetStringTableName();
            of.AddRelocation(ti_reloc);

            for (int i = 0; i < ptr_size; i++, offset++)
            {
                d.Add(0);
            }

            /* IFacePtr */
            IRelocation if_reloc = null;

            if (!ts.IsGenericTemplate && !ts.IsInterface && ts.stype != TypeSpec.SpecialType.Ptr && ts.stype != TypeSpec.SpecialType.MPtr)
            {
                if_reloc            = of.CreateRelocation();
                if_reloc.DefinedIn  = os;
                if_reloc.Offset     = offset;
                if_reloc.Type       = t.GetDataToDataReloc();
                if_reloc.References = sym;
                of.AddRelocation(if_reloc);
            }

            for (int i = 0; i < ptr_size; i++, offset++)
            {
                d.Add(0);
            }

            /* Extends */
            var ts_extends = ts.GetExtends();

            if (ts_extends != null)
            {
                var ext_reloc = of.CreateRelocation();
                ext_reloc.Addend    = 0;
                ext_reloc.DefinedIn = os;
                ext_reloc.Offset    = offset;
                ext_reloc.Type      = t.GetDataToDataReloc();

                var ext_sym = of.CreateSymbol();
                ext_sym.Name = ts_extends.MangleType();

                ext_reloc.References = ext_sym;
                of.AddRelocation(ext_reloc);

                s.r.VTableRequestor.Request(ts_extends);
            }
            for (int i = 0; i < ptr_size; i++, offset++)
            {
                d.Add(0);
            }

            if (ts.IsInterface || ts.IsGenericTemplate || ts.stype == TypeSpec.SpecialType.MPtr || ts.stype == TypeSpec.SpecialType.Ptr)
            {
                /* Type size is zero for somethinh we cannot
                 * instantiate */
                for (int i = 0; i < ptr_size; i++, offset++)
                {
                    d.Add(0);
                }

                /* Flags */
                AddFlags(d, ts, ref offset, t);

                /* BaseType */
                AddBaseType(d, ts, of, os, ref offset, t, s);

                // Target-specific information
                t.AddExtraVTableFields(ts, d, ref offset);
            }
            else
            {
                /* Type size */
                var tsize = t.IntPtrArray(BitConverter.GetBytes(GetTypeSize(ts, t)));
                foreach (var b in tsize)
                {
                    d.Add(b);
                    offset++;
                }

                /* Flags */
                AddFlags(d, ts, ref offset, t);

                /* BaseType */
                AddBaseType(d, ts, of, os, ref offset, t, s);

                // Target specific information
                t.AddExtraVTableFields(ts, d, ref offset);

                /* Virtual methods */
                OutputVirtualMethods(ts, of, os,
                                     d, ref offset, t, s);

                /* Interface implementations */

                // build list of implemented interfaces
                var ii = ts.ImplementedInterfaces;

                // first, add all interface implementations
                List <ulong> ii_offsets = new List <ulong>();

                for (int i = 0; i < ii.Count; i++)
                {
                    ii_offsets.Add(offset - sym.Offset);
                    OutputInterface(ts, ii[i],
                                    of, os, d, ref offset, t, s);
                    s.r.VTableRequestor.Request(ii[i]);
                }

                // point iface ptr here
                if_reloc.Addend = (long)offset - (long)sym.Offset;
                for (int i = 0; i < ii.Count; i++)
                {
                    // list is pointer to interface declaration, then implementation
                    var id_ptr_sym = of.CreateSymbol();
                    id_ptr_sym.Name = ii[i].MangleType();

                    var id_ptr_reloc = of.CreateRelocation();
                    id_ptr_reloc.Addend     = 0;
                    id_ptr_reloc.DefinedIn  = os;
                    id_ptr_reloc.Offset     = offset;
                    id_ptr_reloc.References = id_ptr_sym;
                    id_ptr_reloc.Type       = t.GetDataToDataReloc();
                    of.AddRelocation(id_ptr_reloc);

                    for (int j = 0; j < ptr_size; j++, offset++)
                    {
                        d.Add(0);
                    }

                    // implementation
                    var ii_ptr_reloc = of.CreateRelocation();
                    ii_ptr_reloc.Addend     = (long)ii_offsets[i];
                    ii_ptr_reloc.DefinedIn  = os;
                    ii_ptr_reloc.Offset     = offset;
                    ii_ptr_reloc.References = sym;
                    ii_ptr_reloc.Type       = t.GetDataToDataReloc();
                    of.AddRelocation(ii_ptr_reloc);

                    for (int j = 0; j < ptr_size; j++, offset++)
                    {
                        d.Add(0);
                    }
                }

                // null terminate the list
                for (int j = 0; j < ptr_size; j++, offset++)
                {
                    d.Add(0);
                }
            }

            sym.Size = (long)(offset - sym.Offset);

            /* Output signature table if any */
            if (data_sect == null)
            {
                data_sect = of.GetDataSection();
            }
            s.sigt.WriteToOutput(of, base_m, t, data_sect);
        }
Пример #15
0
        // TODO: Use ImplementInterface
        private static void OutputInterface(TypeSpec impl_ts,
                                            TypeSpec iface_ts, IBinaryFile of, ISection os,
                                            IList <byte> d, ref ulong offset, Target t,
                                            TysilaState s)
        {
            bool is_boxed = false;

            if (impl_ts.IsBoxed)
            {
                impl_ts  = impl_ts.Unbox;
                is_boxed = true;

                /* 'boxed' versions of each method should unbox the
                 * first parameter to a managed pointer then call
                 * the acutal method
                 */
            }
            /* Iterate through methods */
            var first_mdef = iface_ts.m.GetIntEntry(MetadataStream.tid_TypeDef,
                                                    iface_ts.tdrow, 5);
            var last_mdef = iface_ts.m.GetLastMethodDef(iface_ts.tdrow);

            for (uint mdef_row = first_mdef; mdef_row < last_mdef; mdef_row++)
            {
                MethodSpec iface_ms;
                MethodSpec impl_ms = null;
                iface_ts.m.GetMethodDefRow(MetadataStream.tid_MethodDef,
                                           (int)mdef_row, out iface_ms, iface_ts.gtparams, null);
                iface_ms.type = iface_ts;

                // First determine if there is a relevant MethodImpl entry
                for (int i = 1; i <= impl_ts.m.table_rows[MetadataStream.tid_MethodImpl]; i++)
                {
                    var Class = impl_ts.m.GetIntEntry(MetadataStream.tid_MethodImpl, i, 0);

                    if (Class == impl_ts.tdrow)
                    {
                        int mdecl_id, mdecl_row, mbody_id, mbody_row;
                        impl_ts.m.GetCodedIndexEntry(MetadataStream.tid_MethodImpl, i, 2,
                                                     impl_ts.m.MethodDefOrRef, out mdecl_id, out mdecl_row);
                        MethodSpec mdecl_ms;
                        impl_ts.m.GetMethodDefRow(mdecl_id, mdecl_row, out mdecl_ms, impl_ts.gtparams);

                        if (mdecl_ms.Equals(iface_ms))
                        {
                            impl_ts.m.GetCodedIndexEntry(MetadataStream.tid_MethodImpl, i, 1,
                                                         impl_ts.m.MethodDefOrRef, out mbody_id, out mbody_row);
                            impl_ts.m.GetMethodDefRow(mbody_id, mbody_row, out impl_ms, impl_ts.gtparams);
                            impl_ms.type = impl_ts;
                            break;
                        }
                    }
                }

                // Then iterate through all base classes looking for an implementation
                if (impl_ms == null)
                {
                    impl_ms = GetVirtualMethod(impl_ts, iface_ms, t, true);
                }

                if (iface_ms.MangleMethod().StartsWith("_ZW30System#2ECollections#2EGeneric13IEnumerable`1_G1") && impl_ts.stype == TypeSpec.SpecialType.SzArray)
                {
                    // Special case this so we get the generic IEnumerator<T> rather than the standard IEnumator from System.Array.GetEnumerator

                    // coreclr does something similar for _all_ T[] methods (see https://github.com/dotnet/coreclr/blob/release/2.0.0/src/mscorlib/src/System/Array.cs#L2577)
                    var szarrayhelper = iface_ms.m.GetTypeSpec("System", "SZArrayHelper");
                    var genum_ms      = iface_ms.m.GetMethodSpec(szarrayhelper, "GetEnumerator");
                    genum_ms.gmparams = new TypeSpec[] { impl_ts.other };
                    s.r.MethodRequestor.Request(genum_ms);
                    impl_ms = genum_ms;
                }

                // Vectors implement methods which we need to provide
                if (impl_ms == null && impl_ts.stype == TypeSpec.SpecialType.SzArray)
                {
                    // Build a new method that is based in the vector class
                    impl_ms      = iface_ms;
                    impl_ms.type = new TypeSpec
                    {
                        m        = impl_ts.m,
                        tdrow    = impl_ts.tdrow,
                        stype    = impl_ts.stype,
                        other    = impl_ts.other,
                        gtparams = iface_ms.type.gtparams
                    };
                }

                if (impl_ms != null)
                {
                    if (impl_ms.ReturnType != null && impl_ms.ReturnType.IsValueType && t.NeedsBoxRetType(impl_ms) && (iface_ms.ReturnType == null || (iface_ms.ReturnType != null && !iface_ms.ReturnType.IsValueType)))
                    {
                        impl_ms = impl_ms.Clone();
                        impl_ms.ret_type_needs_boxing = true;
                        s.r.BoxedMethodRequestor.Request(impl_ms);
                    }
                    else if (is_boxed)
                    {
                        impl_ms.is_boxed = true;
                        s.r.BoxedMethodRequestor.Request(impl_ms);
                    }
                    else
                    {
                        s.r.MethodRequestor.Request(impl_ms);
                    }
                }

                // Output reference
                string impl_target = (impl_ms == null) ? "__cxa_pure_virtual" : impl_ms.MangleMethod();
                //if(impl_ms == null)
                //{
                //    System.Diagnostics.Debugger.Break();
                //    var test = GetVirtualMethod(impl_ts, iface_ms, t, true);
                //}

                var impl_sym = of.CreateSymbol();
                impl_sym.Name       = impl_target;
                impl_sym.ObjectType = SymbolObjectType.Function;

                var impl_reloc = of.CreateRelocation();
                impl_reloc.Addend     = 0;
                impl_reloc.DefinedIn  = os;
                impl_reloc.Offset     = offset;
                impl_reloc.References = impl_sym;
                impl_reloc.Type       = t.GetDataToCodeReloc();
                of.AddRelocation(impl_reloc);

                for (int i = 0; i < t.GetPointerSize(); i++, offset++)
                {
                    d.Add(0);
                }
            }
        }
Пример #16
0
        public static List <InterfaceMethodImplementation> ImplementInterface(
            TypeSpec impl_ts, TypeSpec iface_ts, Target t, TysilaState s)
        {
            var  ret      = new List <InterfaceMethodImplementation>();
            bool is_boxed = false;

            if (impl_ts.IsBoxed)
            {
                impl_ts  = impl_ts.Unbox;
                is_boxed = true;

                /* 'boxed' versions of each method should unbox the
                 * first parameter to a managed pointer then call
                 * the acutal method
                 */
            }
            /* Iterate through methods */
            var first_mdef = iface_ts.m.GetIntEntry(MetadataStream.tid_TypeDef,
                                                    iface_ts.tdrow, 5);
            var last_mdef = iface_ts.m.GetLastMethodDef(iface_ts.tdrow);

            for (uint mdef_row = first_mdef; mdef_row < last_mdef; mdef_row++)
            {
                MethodSpec iface_ms;
                MethodSpec impl_ms = null;
                iface_ts.m.GetMethodDefRow(MetadataStream.tid_MethodDef,
                                           (int)mdef_row, out iface_ms, iface_ts.gtparams, null);
                iface_ms.type = iface_ts;

                // First determine if there is a relevant MethodImpl entry
                for (int i = 1; i <= impl_ts.m.table_rows[MetadataStream.tid_MethodImpl]; i++)
                {
                    var Class = impl_ts.m.GetIntEntry(MetadataStream.tid_MethodImpl, i, 0);

                    if (Class == impl_ts.tdrow)
                    {
                        int mdecl_id, mdecl_row, mbody_id, mbody_row;
                        impl_ts.m.GetCodedIndexEntry(MetadataStream.tid_MethodImpl, i, 2,
                                                     impl_ts.m.MethodDefOrRef, out mdecl_id, out mdecl_row);
                        MethodSpec mdecl_ms;
                        impl_ts.m.GetMethodDefRow(mdecl_id, mdecl_row, out mdecl_ms, impl_ts.gtparams);

                        /*if (MetadataStream.CompareString(mdecl_ms.m,
                         *  mdecl_ms.m.GetIntEntry(MetadataStream.tid_MethodDef, mdecl_ms.mdrow, 3),
                         *  iface_ms.m,
                         *  iface_ms.m.GetIntEntry(MetadataStream.tid_MethodDef, iface_ms.mdrow, 3)) &&
                         *  MetadataStream.CompareSignature(mdecl_ms, iface_ms))*/
                        if (mdecl_ms.Equals(iface_ms))
                        {
                            impl_ts.m.GetCodedIndexEntry(MetadataStream.tid_MethodImpl, i, 1,
                                                         impl_ts.m.MethodDefOrRef, out mbody_id, out mbody_row);
                            impl_ts.m.GetMethodDefRow(mbody_id, mbody_row, out impl_ms, impl_ts.gtparams);
                            impl_ms.type = impl_ts;
                            break;
                        }
                    }
                }

                // Then iterate through all base classes looking for an implementation
                if (impl_ms == null)
                {
                    impl_ms = GetVirtualMethod(impl_ts, iface_ms, t, true);
                }

                // Vectors implement methods which we need to provide
                if (impl_ms == null && impl_ts.stype == TypeSpec.SpecialType.SzArray)
                {
                    // Build a new method that is based in the vector class
                    impl_ms      = iface_ms;
                    impl_ms.type = new TypeSpec
                    {
                        m        = impl_ts.m,
                        tdrow    = impl_ts.tdrow,
                        stype    = impl_ts.stype,
                        other    = impl_ts.other,
                        gtparams = iface_ms.type.gtparams
                    };
                }

                if (impl_ms != null)
                {
                    if (impl_ms.ReturnType != null && impl_ms.ReturnType.IsValueType && t.NeedsBoxRetType(impl_ms) && (iface_ms.ReturnType == null || (iface_ms.ReturnType != null && !iface_ms.ReturnType.IsValueType)))
                    {
                        impl_ms = impl_ms.Clone();
                        impl_ms.ret_type_needs_boxing = true;
                        s.r.BoxedMethodRequestor.Request(impl_ms);
                    }
                    if (is_boxed)
                    {
                        impl_ms.is_boxed = true;
                        s.r.BoxedMethodRequestor.Request(impl_ms);
                    }
                    else
                    {
                        s.r.MethodRequestor.Request(impl_ms);
                    }
                }

                ret.Add(new InterfaceMethodImplementation {
                    InterfaceMethod = iface_ms, ImplementationMethod = impl_ms
                });
            }
            return(ret);
        }
Пример #17
0
        public unsafe override bool AssembleJitStub(MethodSpec ms, Target t, IBinaryFile bf, TysilaState s)
        {
            var tsect = bf.GetTextSection();
            var mname = ms.MangleMethod();

            // Align to 16 byte boundary
            while ((tsect.Data.Count & 0xf) != 0)
            {
                tsect.Data.Add(0);
            }

            // First comes a pointer to the MethodSpec for this type, followed by a state flag (starts at 0)
            var ms_ptr   = libsupcs.CastOperations.ReinterpretAsUlong(ms);
            var ms_ptr_b = BitConverter.GetBytes(ms_ptr);

            foreach (var bi in ms_ptr_b)
            {
                tsect.Data.Add(bi);
            }

            for (int i = 0; i < 8; i++)
            {
                tsect.Data.Add(0);
            }

            // Add symbol
            var sym = bf.CreateSymbol();

            sym.Name       = mname;
            sym.ObjectType = SymbolObjectType.Function;
            sym.Offset     = (ulong)tsect.Data.Count;
            sym.Type       = SymbolType.Weak;
            tsect.AddSymbol(sym);

            // The code here comes from libtysila5/target/x86/x86_64-jitstub.asm
            var b = new byte[]
            {
                0x83, 0x3d, 0xf1, 0xff, 0xff, 0xff, 0x02,
                0x74, 0x58,
                0x57,
                0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00,
                0x31, 0xc0,
                0xf0, 0x0f, 0xb1, 0x3d, 0xdd, 0xff, 0xff,
                0xff,
                0x83, 0xf8, 0x01,
                0x7c, 0x06,
                0x7f, 0x3e,
                0xf3, 0x90,
                0xeb, 0xeb,
                0x56,
                0x52,
                0x51,
                0x41, 0x50,
                0x41, 0x51,
                0x41, 0x52,
                0x41, 0x53,
                0x48, 0x8b, 0x3d, 0xb8, 0xff, 0xff, 0xff,
                0x48, 0xb8
            };

            foreach (var bi in b)
            {
                tsect.Data.Add(bi);
            }

            // Next comes the 64-bit address of jit_tm
            var jit_tm_addr   = libsupcs.CastOperations.ReinterpretAs <ulong>(libsupcs.OtherOperations.GetFunctionAddress("jit_tm"));
            var jit_tm_addr_b = BitConverter.GetBytes(jit_tm_addr);

            foreach (var bi in jit_tm_addr_b)
            {
                tsect.Data.Add(bi);
            }

            // Continue with the rest of the function
            b = new byte[]
            {
                0xff, 0xd0,
                0x41, 0x5b,
                0x41, 0x5a,
                0x41, 0x59,
                0x41, 0x58,
                0x59,
                0x5a,
                0x5e,
                0x48, 0x89, 0x05, 0x9a, 0xff, 0xff, 0xff,
                0xc7, 0x05, 0x98, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
                0x5f,
                0xff, 0x25, 0x89, 0xff, 0xff, 0xff
            };
            foreach (var bi in b)
            {
                tsect.Data.Add(bi);
            }

            return(true);
        }
Пример #18
0
        protected internal override Code AssembleBoxRetTypeMethod(MethodSpec ms, TysilaState s)
        {
            // Move all parameters up one - this will require knowledge of the param locs
            // if the return type is an object (to get the 'from' locations) and
            // knowledge of the param locs in the target method (the 'to' locations)
            // Allocate space on heap (boxed return object)

            var cc           = cc_map[ms.CallingConvention];
            var cc_class_map = cc_classmap[ms.CallingConvention];
            int stack_loc    = 0;
            var from_locs    = GetRegLocs(new ir.Param
            {
                m  = ms.m,
                ms = ms,
            }, ref stack_loc, cc, cc_class_map,
                                          ms.CallingConvention,
                                          out var from_sizes, out var from_types,
                                          null);

            stack_loc = 0;
            var to_locs = GetRegLocs(new ir.Param
            {
                m  = ms.m,
                ms = ms,
            }, ref stack_loc, cc, cc_class_map,
                                     ms.CallingConvention,
                                     out var to_sizes, out var to_types,
                                     ms.m.SystemIntPtr);

            // Generate code
            var c = new Code();

            c.mc = new List <MCInst>();
            c.s  = s;
            var n  = new cil.CilNode(ms, 0);
            var ir = new cil.CilNode.IRNode {
                parent = n, mc = c.mc
            };

            ir.opcode = Opcode.oc_nop;
            n.irnodes.Add(ir);
            c.starts = new List <cil.CilNode>();
            c.starts.Add(n);
            c.ms = ms;
            c.t  = this;

            // copy from[0:n] to to[1:n+1] in reverse order so
            //  we don't overwrite the previous registers
            ulong defined = 0;

            for (int i = from_locs.Length - 1; i >= 0; i--)
            {
                handle_move(to_locs[i + 1], from_locs[i], c.mc, ir, c, x86_64.x86_64_Assembler.r_rax, from_sizes[i]);
                defined |= to_locs[i + 1].mask;
            }

            // call gcmalloc with the size of the boxed version of the return
            //  type
            var ts          = ms.ReturnType;
            var tsize       = GetSize(ts);
            var sysobj_size = layout.Layout.GetTypeSize(c.ms.m.SystemObject, c.t);
            var boxed_size  = util.util.align(sysobj_size + tsize, psize);

            // decide on the registers we need to save around gcmalloc
            var caller_preserves = cc_caller_preserves_map[ms.CallingConvention];
            var to_push          = new util.Set();

            to_push.Union(defined);
            to_push.Intersect(caller_preserves);
            List <Reg> push_list = new List <Reg>();

            while (!to_push.Empty)
            {
                var first_set = to_push.get_first_set();
                push_list.Add(c.t.regs[first_set]);
                to_push.unset(first_set);
            }
            int push_length = 0;

            foreach (var r in push_list)
            {
                handle_push(r, ref push_length, c.mc, ir, c);
            }
            c.mc.Add(inst(x86_call_rel32, new Param {
                t = Opcode.vl_call_target, str = "gcmalloc"
            },
                          new Param {
                t = Opcode.vl_c32, v = boxed_size
            }, ir));
            for (int i = push_list.Count - 1; i >= 0; i--)
            {
                handle_pop(push_list[i], ref push_length, c.mc, ir, c);
            }

            // put vtable pointer into gcmalloc result
            c.mc.Add(inst(x86_mov_rm32_lab, new ContentsReg {
                basereg = r_eax, size = 4
            },
                          new Param {
                t = Opcode.vl_str, str = ts.MangleType()
            }, ir));

            // put rax into to[0]
            handle_move(to_locs[0], r_eax, c.mc, ir, c);

            // unbox to[0] (i.e. increment pointer so it points to the inner data)
            c.mc.Add(inst(psize == 4 ? x86_add_rm32_imm8 : x86_add_rm64_imm8, to_locs[0], sysobj_size, ir));

            // call the actual function (see AssembleBoxedMethod below)
            var unboxed  = ms.Unbox;
            var act_meth = unboxed.MangleMethod();

            s.r.MethodRequestor.Request(unboxed);

            // Save rax around the call and return it
            // We do this because the actual method returns the address of a value type in rax
            //  and we want to return the address of the boxed object instead
            c.mc.Add(inst(x86_push_r32, r_eax, ir));
            c.mc.Add(inst(x86_call_rel32, new Param {
                t = Opcode.vl_str, str = act_meth
            }, ir));
            c.mc.Add(inst(x86_pop_r32, r_eax, ir));
            c.mc.Add(inst(x86_ret, ir));

            return(c);
        }
Пример #19
0
 protected internal abstract Code AssembleBoxRetTypeMethod(metadata.MethodSpec ms, TysilaState s);
Пример #20
0
 internal static Code CreateArrayAddress(MethodSpec ms,
                                         Target t, TysilaState s)
 {
     throw new NotImplementedException();
 }
Пример #21
0
        private static void CreateDelegateInvoke(TypeSpec ts, Target t, TysilaState s)
        {
            var ms = ts.m.GetMethodSpec(ts, "Invoke", 0, null);

            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            List <cil.CilNode.IRNode> ret = new List <cil.CilNode.IRNode>();

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>();
            TypeSpec fld_ts;

            // Enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // Load m_target
            stack_before = ConvertToIR.ldarg(n, c, stack_before, 0);
            stack_before = ConvertToIR.ldflda(n, c, stack_before, false, out fld_ts, 0, delegate_m_target);
            stack_before = ConvertToIR.binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ConvertToIR.ldind(n, c, stack_before, fld_ts);

            // Duplicate and branch to the static implementation if null
            stack_before = ConvertToIR.copy_to_front(n, c, stack_before);
            stack_before = ConvertToIR.ldc(n, c, stack_before, 0, (int)CorElementType.Object);
            var tstatic = c.next_mclabel--;

            stack_before = ConvertToIR.brif(n, c, stack_before, Opcode.cc_eq, tstatic);
            var tstatic_stack_in = new util.Stack <StackItem>(stack_before);

            // Get number of params and push left to right
            var sig_idx = ms.msig;
            var pcount  = ms.m.GetMethodDefSigParamCount(sig_idx);

            for (int i = 0; i < pcount; i++)
            {
                stack_before = ConvertToIR.ldarg(n, c, stack_before, i + 1);
            }

            // Load method_ptr
            stack_before = ConvertToIR.ldarg(n, c, stack_before, 0);
            stack_before = ConvertToIR.ldflda(n, c, stack_before, false, out fld_ts, 0, delegate_method_ptr);
            stack_before = ConvertToIR.binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ConvertToIR.ldind(n, c, stack_before, fld_ts);

            // Build new method signature containing System.Object followed by the parameters of Invoke
            sig_idx = ms.m.GetMethodDefSigRetTypeIndex(sig_idx);
            var             ret_ts = ms.m.GetTypeSpec(ref sig_idx, ms.gtparams, ms.gmparams);
            List <TypeSpec> p      = new List <TypeSpec>();

            p.Add(ms.m.SystemObject);
            for (int i = 0; i < pcount; i++)
            {
                p.Add(ms.m.GetTypeSpec(ref sig_idx, ms.gtparams, ms.gmparams));
            }
            var new_msig = c.special_meths.CreateMethodSignature(ret_ts, p.ToArray());

            c.ret_ts = ret_ts;

            // Calli
            stack_before = ConvertToIR.call(n, c, stack_before, true, "noname", c.special_meths, new_msig);

            // Ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ((ret_ts == null) ? ir.Opcode.ct_unknown : Opcode.GetCTFromType(ret_ts)), stack_before = stack_before, stack_after = stack_before
            });

            // Static version of above
            stack_before = mclabel(n, c, tstatic_stack_in, tstatic);
            stack_before = ConvertToIR.pop(n, c, stack_before); // remove null m_target pointer

            // Get number of params and push left to right
            sig_idx = ms.msig;
            pcount  = ms.m.GetMethodDefSigParamCount(sig_idx);
            for (int i = 0; i < pcount; i++)
            {
                stack_before = ConvertToIR.ldarg(n, c, stack_before, i + 1);
            }

            // Load method_ptr
            stack_before = ConvertToIR.ldarg(n, c, stack_before, 0);
            stack_before = ConvertToIR.ldflda(n, c, stack_before, false, out fld_ts, 0, delegate_method_ptr);
            stack_before = ConvertToIR.binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ConvertToIR.ldind(n, c, stack_before, fld_ts);

            // Build new method signature containing the parameters of Invoke
            sig_idx = ms.m.GetMethodDefSigRetTypeIndex(sig_idx);
            ret_ts  = ms.m.GetTypeSpec(ref sig_idx, ms.gtparams, ms.gmparams);
            p       = new List <TypeSpec>();
            for (int i = 0; i < pcount; i++)
            {
                p.Add(ms.m.GetTypeSpec(ref sig_idx, ms.gtparams, ms.gmparams));
            }
            new_msig = c.special_meths.CreateMethodSignature(ret_ts, p.ToArray());
            c.ret_ts = ret_ts;

            // Calli
            stack_before = ConvertToIR.call(n, c, stack_before, true, "noname", c.special_meths, new_msig);

            // Ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ((ret_ts == null) ? ir.Opcode.ct_unknown : Opcode.GetCTFromType(ret_ts)), stack_before = stack_before, stack_after = stack_before
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            var msc = new layout.Layout.MethodSpecWithEhdr
            {
                ms = ms,
                c  = c
            };

            s.r.MethodRequestor.Remove(msc);
            s.r.MethodRequestor.Request(msc);
        }
Пример #22
0
        internal static Code CreateArrayCtor1(MethodSpec ms,
                                              Target t, TysilaState s)
        {
            Code c = new Code {
                t = t, ms = ms, s = s
            };

            t.AllocateLocalVarsArgs(c);
            cil.CilNode n = new cil.CilNode(ms, 0);

            List <cil.CilNode.IRNode> ret = new List <cil.CilNode.IRNode>();

            util.Stack <StackItem> stack_before = new util.Stack <StackItem>(0);

            // Enter
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_enter, stack_before = stack_before, stack_after = stack_before
            });

            // Set elem type vtbl pointer
            stack_before = ldarg(n, c, stack_before, 0);
            stack_before = ldc(n, c, stack_before, layout.Layout.GetArrayFieldOffset(layout.Layout.ArrayField.ElemTypeVtblPointer, t), 0x18);
            stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ldlab(n, c, stack_before, ms.type.other.MangleType());
            s.r.VTableRequestor.Request(ms.type.other.Box);
            stack_before = stind(n, c, stack_before, t.GetPointerSize());

            // Set lobounds array and pointer
            stack_before = ldarg(n, c, stack_before, 0);
            stack_before = ldc(n, c, stack_before, layout.Layout.GetArrayFieldOffset(layout.Layout.ArrayField.LoboundsPointer, t), 0x18);
            stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ldc(n, c, stack_before, t.GetSize(ms.m.SystemInt32) * ms.type.arr_rank);
            stack_before = call(n, c, stack_before, false, "gcmalloc", c.special_meths, c.special_meths.gcmalloc);
            for (int i = 0; i < ms.type.arr_rank; i++)
            {
                stack_before = copy_to_front(n, c, stack_before);
                if (i != 0)
                {
                    stack_before = ldc(n, c, stack_before, t.GetSize(ms.m.SystemInt32) * i, 0x18);
                    stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
                }
                stack_before = ldc(n, c, stack_before, 0); // lobounds implied to be 0
                stack_before = stind(n, c, stack_before, t.GetSize(ms.m.SystemInt32));
            }
            stack_before = stind(n, c, stack_before, t.GetPointerSize());

            // Set sizes array and pointer
            stack_before = ldarg(n, c, stack_before, 0);
            stack_before = ldc(n, c, stack_before, layout.Layout.GetArrayFieldOffset(layout.Layout.ArrayField.SizesPointer, t), 0x18);
            stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ldc(n, c, stack_before, t.GetSize(ms.m.SystemInt32) * ms.type.arr_rank);
            stack_before = call(n, c, stack_before, false, "gcmalloc", c.special_meths, c.special_meths.gcmalloc);
            for (int i = 0; i < ms.type.arr_rank; i++)
            {
                stack_before = copy_to_front(n, c, stack_before);
                if (i != 0)
                {
                    stack_before = ldc(n, c, stack_before, t.GetSize(ms.m.SystemInt32) * i, 0x18);
                    stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
                }
                stack_before = ldarg(n, c, stack_before, 1 + i);
                stack_before = stind(n, c, stack_before, t.GetSize(ms.m.SystemInt32));
            }
            stack_before = stind(n, c, stack_before, t.GetPointerSize());

            // Set data array pointer
            stack_before = ldarg(n, c, stack_before, 0);
            stack_before = ldc(n, c, stack_before, layout.Layout.GetArrayFieldOffset(layout.Layout.ArrayField.DataArrayPointer, t), 0x18);
            stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            if (ms.type.arr_rank == 0)
            {
                stack_before = ldc(n, c, stack_before, 0);
            }
            else
            {
                stack_before = ldarg(n, c, stack_before, 1);    // don't need to subtract lobounds for ctor1
            }
            for (int i = 1; i < ms.type.arr_rank; i++)
            {
                stack_before = ldarg(n, c, stack_before, 1 + i);    // load size
                // don't need to subtract lobounds here
                stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.mul);
            }
            var et_size = t.GetSize(ms.type.other);

            if (et_size > 1)
            {
                stack_before = ldc(n, c, stack_before, et_size);
                stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.mul);
            }
            stack_before = call(n, c, stack_before, false, "gcmalloc", c.special_meths, c.special_meths.gcmalloc);
            stack_before = stind(n, c, stack_before, t.GetPointerSize());

            // Set Rank
            stack_before = ldarg(n, c, stack_before, 0);
            stack_before = ldc(n, c, stack_before, layout.Layout.GetArrayFieldOffset(layout.Layout.ArrayField.Rank, t), 0x18);
            stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ldc(n, c, stack_before, ms.type.arr_rank);
            stack_before = stind(n, c, stack_before, t.GetSize(ms.m.SystemInt32));

            // Set Elem Size
            stack_before = ldarg(n, c, stack_before, 0);
            stack_before = ldc(n, c, stack_before, layout.Layout.GetArrayFieldOffset(layout.Layout.ArrayField.ElemTypeSize, t), 0x18);
            stack_before = binnumop(n, c, stack_before, cil.Opcode.SingleOpcodes.add, Opcode.ct_intptr);
            stack_before = ldc(n, c, stack_before, et_size);
            stack_before = stind(n, c, stack_before, t.GetSize(ms.m.SystemInt32));

            // Ret
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_ret, ct = ir.Opcode.ct_unknown, stack_before = stack_before, stack_after = stack_before
            });

            c.cil = new List <cil.CilNode> {
                n
            };
            c.ir = n.irnodes;

            c.starts = new List <cil.CilNode> {
                n
            };

            return(c);
        }
Пример #23
0
 protected internal override Code AssembleBoxedMethod(MethodSpec ms, TysilaState s)
 {
     throw new NotImplementedException();
 }