Exemple #1
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);
        }
Exemple #2
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);
        }
Exemple #3
0
        private static util.Stack <StackItem> exit_cli(cil.CilNode n, Code c, util.Stack <StackItem> stack_before)
        {
            var stack_after = new util.Stack <StackItem>(stack_before);

            stack_after.Pop();
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_target_specific, imm_l = x86_exit_cli, stack_before = stack_before, stack_after = stack_after
            });

            return(stack_after);
        }
Exemple #4
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);
        }
Exemple #5
0
        private static util.Stack <StackItem> portout_dword(cil.CilNode n, Code c, util.Stack <StackItem> stack_before)
        {
            var stack_after = new util.Stack <StackItem>(stack_before);

            stack_after.Pop();
            stack_after.Pop();

            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = ir.Opcode.oc_x86_portout, vt_size = 4, stack_before = stack_before, stack_after = stack_after, arg_a = 1, arg_b = 0
            });

            return(stack_after);
        }
Exemple #6
0
        private static util.Stack <StackItem> enter_cli(cil.CilNode n, Code c, util.Stack <StackItem> stack_before)
        {
            var stack_after = new util.Stack <StackItem>(stack_before);

            stack_after.Push(new StackItem {
                ts = c.ms.m.SystemIntPtr
            });
            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = Opcode.oc_target_specific, imm_l = x86_enter_cli, stack_before = stack_before, stack_after = stack_after
            });

            return(stack_after);
        }
Exemple #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);
        }
Exemple #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);
        }
Exemple #9
0
        private static util.Stack <StackItem> portin_dword(cil.CilNode n, Code c, util.Stack <StackItem> stack_before)
        {
            var stack_after = new util.Stack <StackItem>(stack_before);

            stack_after.Pop();
            stack_after.Push(new StackItem {
                ts = c.ms.m.SystemUInt32, min_ul = 0, max_ul = uint.MaxValue
            });

            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = ir.Opcode.oc_x86_portin, vt_size = 4, stack_before = stack_before, stack_after = stack_after, arg_a = 0, res_a = 0
            });

            return(stack_after);
        }
Exemple #10
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);
        }
Exemple #11
0
        private static util.Stack <StackItem> math_Round(cil.CilNode n, Code c, util.Stack <StackItem> stack_before)
        {
            var stack_after = new util.Stack <StackItem>(stack_before);

            var old = stack_after.Pop();

            // propagate immediate value if there is one
            double min_imm = Math.Round(BitConverter.ToDouble(BitConverter.GetBytes(old.min_ul), 0));
            double max_imm = Math.Round(BitConverter.ToDouble(BitConverter.GetBytes(old.max_ul), 0));

            stack_after.Push(new StackItem {
                ts = c.ms.m.GetSimpleTypeSpec(0xd), min_ul = BitConverter.ToUInt64(BitConverter.GetBytes(min_imm), 0), max_ul = BitConverter.ToUInt64(BitConverter.GetBytes(max_imm), 0)
            });

            n.irnodes.Add(new cil.CilNode.IRNode {
                parent = n, opcode = ir.Opcode.oc_target_specific, imm_l = x86_roundsd_xmm_xmmm64_imm8, stack_before = stack_before, stack_after = stack_after, arg_a = 0, res_a = 0
            });

            return(stack_after);
        }
Exemple #12
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);
        }
Exemple #13
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);
        }
Exemple #14
0
        private static util.Stack <StackItem> ArrayGetIndex(Code c, cil.CilNode n, MethodSpec ms, util.Stack <StackItem> stack_before, Target t)
        {
            /* For a rank 4 array this simplifies to:
             *
             * (r4-r4lb) + r4len[(r3-r3lb) + r3len[(r2-r2lb) + r2len[(r1-r1lb)]]]
             *
             * where len is the 'size' member and lb is the lobounds
             *
             * in ir:
             *
             * ldc r1
             * sub r1lb
             *
             * mul r2len
             * add r2
             * sub r2lb
             *
             * mul r3len
             * add r3
             * sub r3lb
             *
             * mul r4len
             * add r4
             * sub r4lb
             *
             * and we can simplify lobounds/sizes lookups if we know them
             */

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

            // ldc r1
            stack_after = ldarg(n, c, stack_after, 1);

            // sub r1lb
            bool lbzero, szone;    // optimize away situation where lobounds is zero

            stack_after = ArrayGetLobounds(n, c, stack_after, ms, 1, out lbzero);
            if (!lbzero)
            {
                stack_after = binnumop(n, c, stack_after, cil.Opcode.SingleOpcodes.sub, ir.Opcode.ct_int32);
            }

            for (int rank = 2; rank <= ms.type.arr_rank; rank++)
            {
                // mul rnlen
                stack_after = ArrayGetSize(n, c, stack_after, ms, rank, out szone);
                if (!szone)
                {
                    stack_after = binnumop(n, c, stack_after, cil.Opcode.SingleOpcodes.mul, Opcode.ct_int32);
                }

                // add rn
                stack_after = ldarg(n, c, stack_after, rank);
                stack_after = binnumop(n, c, stack_after, cil.Opcode.SingleOpcodes.add, Opcode.ct_int32);

                // sub rnlb
                stack_after = ArrayGetLobounds(n, c, stack_after, ms, rank, out lbzero);
                if (!lbzero)
                {
                    stack_after = binnumop(n, c, stack_after, cil.Opcode.SingleOpcodes.sub, ir.Opcode.ct_int32);
                }
            }

            return(stack_after);
        }
Exemple #15
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);
        }
Exemple #16
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);
        }
Exemple #17
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);
        }