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); }
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); }
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); }
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); } }
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); }
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); }
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); }
/*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); }
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); }
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); } } }
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); }
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); }
/* 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); }
// 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); } } }
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); }
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); }
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); }
protected internal abstract Code AssembleBoxRetTypeMethod(metadata.MethodSpec ms, TysilaState s);
internal static Code CreateArrayAddress(MethodSpec ms, Target t, TysilaState s) { throw new NotImplementedException(); }
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 AssembleBoxedMethod(MethodSpec ms, TysilaState s) { throw new NotImplementedException(); }