private void GenerateIMTHelpers(Class _class) { if (!_class.IsClass) return; if ((_class.ClassDefinition as TypeDefinition).Interfaces.Count > 0) { for (int i = 0; i < Method.IMTSize; ++i) { List<Method> entries = _class.GetInterfaceEntries (i); if (entries != null && entries.Count > 1) GenerateConflictStub (_class, i); } } }
/// <summary> /// Common implementations which pop a value from the IL evaluation stack and save it in another means /// of storage (such as stloc, stind, starg). /// </summary> private void Save (Class _class, InternalType destinationType, Memory memory, IR.Operands.Register value) { switch (destinationType) { case InternalType.I1: if (value.IsRegisterSet) this.assembly.MOV (R32.EAX, Assembly.GetRegister (value.Register)); else this.assembly.MOV (R32.EAX, new DWordMemory (this.GetAddress (value))); this.assembly.MOV (new ByteMemory (memory), R8.AL); break; case InternalType.U1: if (value.IsRegisterSet) this.assembly.MOV (R32.EAX, Assembly.GetRegister (value.Register)); else this.assembly.MOV (R32.EAX, new DWordMemory (this.GetAddress (value))); this.assembly.MOV (new ByteMemory (memory), R8.AL); break; case InternalType.I2: if (value.IsRegisterSet) this.assembly.MOV (R32.EAX, Assembly.GetRegister (value.Register)); else this.assembly.MOV (R32.EAX, new DWordMemory (this.GetAddress (value))); this.assembly.MOV (new WordMemory (memory), R16.AX); break; case InternalType.U2: if (value.IsRegisterSet) this.assembly.MOV (R32.EAX, Assembly.GetRegister (value.Register)); else this.assembly.MOV (R32.EAX, new DWordMemory (this.GetAddress (value))); this.assembly.MOV (new WordMemory (memory), R16.AX); break; case InternalType.I4: case InternalType.U4: case InternalType.I: case InternalType.U: case InternalType.O: case InternalType.SZArray: case InternalType.Array: if (value.IsRegisterSet) this.assembly.MOV (R32.EAX, Assembly.GetRegister (value.Register)); else this.assembly.MOV (R32.EAX, new DWordMemory (this.GetAddress (value))); this.assembly.MOV (new DWordMemory (memory), R32.EAX); break; case InternalType.I8: case InternalType.U8: Memory source = this.GetAddress (value); source.DisplacementDelta = 4; DWordMemory destination = new DWordMemory (memory); destination.DisplacementDelta = 4; this.assembly.MOV (R32.EAX, new DWordMemory (this.GetAddress (value))); this.assembly.MOV (new DWordMemory (memory), R32.EAX); this.assembly.MOV (R32.EAX, new DWordMemory (source)); this.assembly.MOV (new DWordMemory (destination), R32.EAX); break; case InternalType.ValueType: uint size = (uint) this.method.Engine.GetTypeSize (_class.TypeFullName, 4); if (size == 4) { if (value.IsRegisterSet) this.assembly.MOV (R32.EAX, Assembly.GetRegister (value.Register)); else this.assembly.MOV (R32.EAX, new DWordMemory (this.GetAddress (value))); this.assembly.MOV (new DWordMemory (memory), R32.EAX); } else { this.assembly.PUSH (R32.ECX); this.assembly.PUSH (R32.ESI); this.assembly.PUSH (R32.EDI); if (value.IsRegisterSet) this.assembly.MOV (R32.ESI, Assembly.GetRegister (value.Register)); else this.assembly.LEA (R32.ESI, new DWordMemory (this.GetAddress (value))); this.assembly.LEA (R32.EDI, new DWordMemory (memory)); this.assembly.MOV (R32.ECX, size); this.assembly.CLD (); this.assembly.REP (); this.assembly.MOVSB (); this.assembly.POP (R32.EDI); this.assembly.POP (R32.ESI); this.assembly.POP (R32.ECX); } break; case InternalType.R4: case InternalType.R8: case InternalType.F: case InternalType.M: case InternalType.TypedReference: default: throw new NotImplementedEngineException ("Save not supported for InternalType." + destinationType); } }
private void GenerateConflictStubPart (Class _class, int key, List<Method> methods, int rangeStart, int rangeEnd) { // only one element - just jump to that method if (rangeStart == rangeEnd) { this.JMP (methods[rangeStart].AssemblyLabel); } else { // many elements - divide and generate stub parts int divide = (rangeEnd - rangeStart)/2 + rangeStart; string greaterBranchLabel = GetITableStubPartLabel(_class, key, divide+1, rangeEnd); this.CMP (R32.ECX, (uint)methods[divide].InterfaceMethodNumber); this.JG (greaterBranchLabel); // needed interface number is lower than middle element GenerateConflictStubPart (_class, key, methods, rangeStart, divide); this.LABEL (greaterBranchLabel); // needed interface number is higher than middle element GenerateConflictStubPart (_class, key, methods, divide + 1, rangeEnd); } }
private void GenerateConflictStub (Class _class, int key) { List<Method> entries = _class.GetInterfaceEntries (key); entries.Sort (delegate (Method a, Method b) { return Comparer<int>.Default.Compare (a.InterfaceMethodNumber, b.InterfaceMethodNumber); }); string fullname = GetITableStubLabel(_class, key); this.ALIGN (Assembly.ALIGNMENT); this.AddSymbol (new COFF.Function (fullname)); this.LABEL (fullname); GenerateConflictStubPart (_class, key, entries, 0, entries.Count-1); }
private string AddTypeInfoFields (Class _class) { this.ALIGN (OBJECT_ALIGNMENT); // Writing the Type Info instances string typeInfoLabel = this.GetTypeInfoLabel (_class.TypeFullName); this.AddSymbol (new COFF.Label (typeInfoLabel)); this.LABEL (typeInfoLabel); // Type Info Object Header this.AddObjectFields (this.engine.TypeInfoClass.TypeFullName); // Type Info Name this.ADDRESSOF (this.AddString (_class.TypeFullName)); // Type Info Base Instance if (_class.Base == null) // NULL this.DATA ((uint) 0); else this.ADDRESSOF (this.GetTypeInfoLabel (_class.Base.TypeFullName)); if (this.engine.Options.NoMetadata) { this.DATA (0U); this.DATA (0U); } else { // Type Info AssemblyMetadata this.ADDRESSOF (_class.ClassDefinition.Module.Assembly.Name + " MetadataRoot"); /*if (_class.ClassDefinition.Name == "TestD") Console.WriteLine ("TestD ******: {0}", _class.ClassDefinition.MetadataToken.ToUInt ().ToString ("x"));*/ // Type Info Metadata token this.DATA (_class.ClassDefinition.MetadataToken.ToUInt ()); } return typeInfoLabel; }
private void AddITableFields (Class _class) { this.ALIGN (OBJECT_ALIGNMENT); // Writing the Runtime ITable instances string label = this.GetITableLabel (_class.TypeFullName); this.AddSymbol (new COFF.Label (label)); this.LABEL (label); // Type Info Object Header this.AddObjectFields (this.engine.ITableClass.TypeFullName); // count entries - don't write unused fields int lastEntry=0; for (int key = 0; key < Method.IMTSize; ++key) { if (_class.GetInterfaceEntries(key) != null) lastEntry = key; } for (int key = 0; key <= lastEntry; ++key) { List<Method> m = _class.GetInterfaceEntries(key); if (m == null) { this.DATA((uint) 0); } else if (m.Count == 1) { this.ADDRESSOF (m[0].AssemblyLabel); } else { this.ADDRESSOF (GetITableStubLabel(_class, key)); } } }
private void AddVTableFields (Class _class, string typeInfoLabel) { this.ALIGN (OBJECT_ALIGNMENT); // Writing the Runtime VTable instances string label = this.GetVTableLabel (_class.TypeFullName); this.AddSymbol (new COFF.Label (label)); this.LABEL (label); this.AddObjectFields (this.engine.VTableClass.TypeFullName); /*if (_class.ClassDefinition.Name == "TestD") { Console.WriteLine ("vtable.type -> {0}", typeInfoLabel); }*/ // Type Info Field this.ADDRESSOF (typeInfoLabel); // VTable Size Field this.DATA ((uint) _class.ObjectSize); // ITable pointer if (_class.ImplementsInterfaces) this.ADDRESSOF (this.GetITableLabel(_class.TypeFullName)); else this.DATA ((uint) 0); // Virtual Methods foreach (Method method in _class.VirtualMethods) { // add only non-interface methods to vtable if (method.InterfaceMethodNumber == -1) { this.ADDRESSOF (method.AssemblyLabel); } } }
/// <summary> /// Gets the I table stub part label. /// </summary> /// <param name="_class">The _class.</param> /// <param name="key">The key.</param> /// <param name="fromMethod">From method.</param> /// <param name="toMethod">To method.</param> /// <returns></returns> public string GetITableStubPartLabel (Class _class, int key, int fromMethod, int toMethod) { return string.Format (IMT_RANGE_LABEL, _class, key, fromMethod, toMethod); }
/// <summary> /// Gets the I table stub label. /// </summary> /// <param name="_class">The _class.</param> /// <param name="key">The key.</param> /// <returns></returns> public string GetITableStubLabel (Class _class, int key) { return string.Format (IMT_LABEL, _class, key); }