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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
/*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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }