private CliClass(CliClass baseClass, Compiler compiler, TypeSpecTag[] argTypes) { if (!baseClass.m_isCreated) throw new Exception("Can't instantiate an open class that hasn't been processed"); m_typeName = baseClass.m_typeName; m_parentClassSpec = (TypeSpecClassTag)baseClass.m_parentClassSpec.Instantiate(compiler.TagRepository, argTypes); m_parentClass = compiler.GetClosedClass(m_parentClassSpec); m_isSealed = baseClass.m_isSealed; m_isAbstract = baseClass.m_isAbstract; m_isStruct = baseClass.m_isStruct; m_typeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(new TypeSpecClassTag(m_typeName, argTypes)); m_isCreated = baseClass.m_isCreated; m_numGenericParameters = baseClass.m_numGenericParameters; List<HighField> staticFields = new List<HighField>(); foreach (HighField fld in baseClass.m_staticFields) staticFields.Add(fld.Instantiate(compiler.TagRepository, argTypes)); m_staticFields = staticFields.ToArray(); List<HighMethod> methods = new List<HighMethod>(); foreach (HighMethod method in baseClass.m_methods) methods.Add(method.Instantiate(compiler.TagRepository, argTypes)); m_methods = methods.ToArray(); List<HighField> instanceFields = new List<HighField>(); foreach (HighField fld in baseClass.m_instanceFields) instanceFields.Add(fld.Instantiate(compiler.TagRepository, argTypes)); m_instanceFields = instanceFields.ToArray(); List<CliVtableSlot> vtableSlots = new List<CliVtableSlot>(); foreach (CliVtableSlot slot in baseClass.m_vtable) vtableSlots.Add(slot.Instantiate(compiler, argTypes)); m_vtable = vtableSlots.ToArray(); List<CliInterfaceImpl> interfaceImpls = new List<CliInterfaceImpl>(); foreach (CliInterfaceImpl ifcImpl in baseClass.m_interfaceImpls) interfaceImpls.Add(ifcImpl.Instantiate(compiler, argTypes)); m_interfaceImpls = interfaceImpls.ToArray(); List<TypeSpecClassTag> explicitInterfaces = new List<TypeSpecClassTag>(); foreach (TypeSpecClassTag ifc in baseClass.m_explicitInterfaceSpecs) explicitInterfaces.Add((TypeSpecClassTag)ifc.Instantiate(compiler.TagRepository, argTypes)); m_explicitInterfaceSpecs = explicitInterfaces.ToArray(); m_declTagToMethod = baseClass.m_declTagToMethod; m_declTagToVTableSlot = baseClass.m_declTagToVTableSlot; m_ifcToIfcSlot = baseClass.m_ifcToIfcSlot; m_nameToInstanceFieldSlot = baseClass.m_nameToInstanceFieldSlot; m_nameToStaticFieldSlot = baseClass.m_nameToStaticFieldSlot; }
public PodFlags GetClassPodFlags(Compiler compiler, CliClass cls) { PodFlags podFlags = PodFlags.None; foreach (HighField fld in cls.InstanceFields) { TypeSpecTag fldType = fld.Type; if (!compiler.TypeIsValueType(fldType)) return PodFlags.None; CliClass fldClass = compiler.GetClosedClass((TypeSpecClassTag)fldType); podFlags &= GetClassPodFlags(compiler, fldClass); if (podFlags == PodFlags.None) return PodFlags.None; } return podFlags; }
private List<MethodSpecTag> GenerateMethodSpecsForClass(Compiler compiler, TypeSpecClassTag typeSpec) { CliClass cls = compiler.GetClosedClass(typeSpec); List<MethodSpecTag> methodSpecs = new List<MethodSpecTag>(); foreach (CliVtableSlot vtableSlot in cls.VTable) { if (vtableSlot.MethodSignature.NumGenericParameters > 0) { methodSpecs.Add(null); continue; } CliMethodIndex methodIndex = vtableSlot.MethodIndex; if (methodIndex == null) throw new RpaCompileException("Can't generate vtable slot for abstract method"); methodSpecs.Add(ResolveVirtualMethod(compiler, cls, methodIndex)); } return methodSpecs; }
private List<MethodHandle> GenerateVTableForMulticastDelegate(Compiler compiler, TypeSpecMulticastDelegateTag typeSpec, VTableGenerationCache vtCache) { TypeSpecClassTag delegateType = typeSpec.DelegateType; CliClass cls = compiler.GetClosedClass(delegateType); List<MethodHandle> methodHandles = new List<MethodHandle>(); List<MethodSpecTag> methodSpecs = new List<MethodSpecTag>(); foreach (CliVtableSlot vtableSlot in cls.VTable) { CliMethodIndex methodIndex = vtableSlot.MethodIndex; if (methodIndex == null) methodSpecs.Add(null); else methodSpecs.Add(ResolveVirtualMethod(compiler, cls, methodIndex)); } int numSlots = methodSpecs.Count; for (int i = 0; i < numSlots; i++) methodHandles.Add(null); foreach (KeyValuePair<MethodDeclTag, uint> dtvs in cls.DeclTagToVTableSlot) { int slot = (int)dtvs.Value; MethodDeclTag methodDecl = dtvs.Key; if (methodDecl.Name == "Invoke") { methodHandles[slot] = compiler.InstantiateMethod(new GeneratedMethods.GMMulticastDelegateInvoke(typeSpec.DelegateType, vtCache), m_instantiationPath); methodSpecs[slot] = null; } } for (int i = 0; i < numSlots; i++) { MethodSpecTag methodSpec = methodSpecs[i]; if (methodSpec != null) methodHandles[i] = compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), m_instantiationPath); } return methodHandles; }
public uint GetGetHashCodeVTableSlot(Compiler compiler) { if (m_getHashCodeVTableSlot.HasValue) return m_getHashCodeVTableSlot.Value; MethodSignatureTag signature = new MethodSignatureTag(0, GetSystemInt32Type(compiler), new MethodSignatureParam[0]); signature = compiler.TagRepository.InternMethodSignature(signature); MethodDeclTag declTag = new MethodDeclTag("GetHashCode", signature, GetSystemObjectType(compiler).TypeName); declTag = compiler.TagRepository.InternMethodDeclTag(declTag); CliClass cls = compiler.GetClosedClass(GetSystemObjectType(compiler)); uint result = cls.DeclTagToVTableSlot[declTag]; m_getHashCodeVTableSlot = result; return result; }
public uint GetEqualsVTableSlot(Compiler compiler) { if (m_equalsVTableSlot.HasValue) return m_equalsVTableSlot.Value; MethodSignatureParam[] sigParams = new MethodSignatureParam[1]; sigParams[0] = new MethodSignatureParam(GetSystemObjectType(compiler), new MethodSignatureParamTypeOfType(MethodSignatureParamTypeOfType.Values.Value)); MethodSignatureTag signature = new MethodSignatureTag(0, GetSystemBoolType(compiler), sigParams); signature = compiler.TagRepository.InternMethodSignature(signature); MethodDeclTag declTag = new MethodDeclTag("Equals", signature, GetSystemObjectType(compiler).TypeName); declTag = compiler.TagRepository.InternMethodDeclTag(declTag); CliClass cls = compiler.GetClosedClass(GetSystemObjectType(compiler)); uint result = cls.DeclTagToVTableSlot[declTag]; m_equalsVTableSlot = result; return result; }
public bool Create(Compiler compiler) { HighTypeDef typeDef = compiler.GetTypeDef(m_typeName); TypeSpecClassTag parentClassSpec = null; HighClassVtableSlot[] newSlots; HighClassVtableSlot[] replacedSlots; HighInterfaceImplementation[] typeInterfaceImpls; if (typeDef.Semantics == TypeSemantics.Struct || typeDef.Semantics == TypeSemantics.Class) { if (typeDef.Semantics == TypeSemantics.Struct) { m_isStruct = true; TypeNameTag valueTypeName = new TypeNameTag("mscorlib", "System", "ValueType", 0, null); valueTypeName = compiler.TagRepository.InternTypeName(valueTypeName); TypeSpecClassTag vtClassTag = new TypeSpecClassTag(valueTypeName, new TypeSpecTag[0]); vtClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(vtClassTag); parentClassSpec = vtClassTag; } else if (typeDef.Semantics == TypeSemantics.Class) { m_isStruct = false; parentClassSpec = typeDef.ParentClass; RestrictedExtensionType thisRet = GetRestrictedExtensionType(m_typeName); if (parentClassSpec == null) { if (thisRet != RestrictedExtensionType.Object) throw new Exception("Parentless class is not [mscorlib]System.Object"); } else { if (thisRet == RestrictedExtensionType.Object) throw new Exception("[mscorlib]System.Object has a parent"); RestrictedExtensionType parentRet = GetRestrictedExtensionType(parentClassSpec.TypeName); bool isExtensionOK = false; switch (parentRet) { case RestrictedExtensionType.ValueType: if (thisRet == RestrictedExtensionType.Enum) isExtensionOK = true; break; case RestrictedExtensionType.Delegate: if (thisRet == RestrictedExtensionType.MulticastDelegate) isExtensionOK = true; break; case RestrictedExtensionType.Enum: case RestrictedExtensionType.MulticastDelegate: case RestrictedExtensionType.NullableSZArray: case RestrictedExtensionType.RefSZArray: case RestrictedExtensionType.ValueSZArray: break; case RestrictedExtensionType.Object: case RestrictedExtensionType.None: isExtensionOK = true; break; case RestrictedExtensionType.Array: if (thisRet == RestrictedExtensionType.NullableSZArray || thisRet == RestrictedExtensionType.ValueSZArray || thisRet == RestrictedExtensionType.RefSZArray) isExtensionOK = true; break; default: throw new ArgumentException(); } if (!isExtensionOK) throw new Exception("Invalid extension of a restricted class"); } } m_instanceFields = typeDef.InstanceFields; m_methods = typeDef.Methods; m_staticFields = typeDef.StaticFields; m_isSealed = typeDef.IsSealed; m_isAbstract = typeDef.IsAbstract; replacedSlots = typeDef.ReplacedSlots; newSlots = typeDef.NewSlots; typeInterfaceImpls = typeDef.InterfaceImpls; } else if (typeDef.Semantics == TypeSemantics.Delegate) { m_isStruct = false; TypeNameTag dgTypeName = new TypeNameTag("mscorlib", "System", typeDef.IsMulticastDelegate ? "MulticastDelegate" : "Delegate", 0, null); dgTypeName = compiler.TagRepository.InternTypeName(dgTypeName); TypeSpecClassTag dgClassTag = new TypeSpecClassTag(dgTypeName, new TypeSpecTag[0]); dgClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(dgClassTag); parentClassSpec = dgClassTag; m_instanceFields = new HighField[0]; m_methods = new HighMethod[0]; m_staticFields = new HighField[0]; m_isSealed = false; m_isAbstract = true; replacedSlots = new HighClassVtableSlot[0]; MethodDeclTag invokeTag = new MethodDeclTag("Invoke", typeDef.DelegateSignature, m_typeName); invokeTag = compiler.TagRepository.InternMethodDeclTag(invokeTag); HighClassVtableSlot invokeSlot = new HighClassVtableSlot(invokeTag, typeDef.DelegateSignature, null, true, false); newSlots = new HighClassVtableSlot[1] { invokeSlot }; typeInterfaceImpls = new HighInterfaceImplementation[0]; } else if (typeDef.Semantics == TypeSemantics.Enum) { m_isStruct = false; TypeNameTag dgTypeName = new TypeNameTag("mscorlib", "System", "Enum", 0, null); dgTypeName = compiler.TagRepository.InternTypeName(dgTypeName); TypeSpecClassTag dgClassTag = new TypeSpecClassTag(dgTypeName, new TypeSpecTag[0]); dgClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(dgClassTag); parentClassSpec = dgClassTag; string underlyingTypeName; switch (typeDef.UnderlyingType) { case HighTypeDef.EnumUnderlyingType.Int8: underlyingTypeName = "SByte"; break; case HighTypeDef.EnumUnderlyingType.Int16: underlyingTypeName = "Int16"; break; case HighTypeDef.EnumUnderlyingType.Int32: underlyingTypeName = "Int32"; break; case HighTypeDef.EnumUnderlyingType.Int64: underlyingTypeName = "Int64"; break; case HighTypeDef.EnumUnderlyingType.UInt8: underlyingTypeName = "Byte"; break; case HighTypeDef.EnumUnderlyingType.UInt16: underlyingTypeName = "Int16"; break; case HighTypeDef.EnumUnderlyingType.UInt32: underlyingTypeName = "UInt32"; break; case HighTypeDef.EnumUnderlyingType.UInt64: underlyingTypeName = "UInt64"; break; default: throw new Exception(); } TypeNameTag underlyingTypeNameTag = new TypeNameTag("mscorlib", "System", underlyingTypeName); underlyingTypeNameTag = compiler.TagRepository.InternTypeName(underlyingTypeNameTag); TypeSpecClassTag underlyingTypeSpec = new TypeSpecClassTag(underlyingTypeNameTag, new TypeSpecTag[0]); underlyingTypeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(underlyingTypeSpec); HighField fld = new HighField("value__", underlyingTypeSpec); m_instanceFields = new HighField[1] { fld }; m_methods = new HighMethod[0]; m_staticFields = new HighField[0]; m_isSealed = true; m_isAbstract = false; replacedSlots = new HighClassVtableSlot[0]; newSlots = new HighClassVtableSlot[0]; typeInterfaceImpls = new HighInterfaceImplementation[0]; } else throw new ArgumentException(); if (parentClassSpec != null) { if (compiler.GetTypeDef(parentClassSpec.TypeName).Semantics != TypeSemantics.Class) throw new RpaCompileException("Can't extend class with non-class semantics"); if (!compiler.HaveCliOpenClass(parentClassSpec.TypeName)) return false; CliClass parentClass = compiler.GetClosedClass(parentClassSpec); if (parentClass.m_isSealed) throw new RpaCompileException("Can't extend sealed CLI class"); m_parentClass = parentClass; } m_numGenericParameters = typeDef.NumGenericParameters; // Update vtable { Dictionary<MethodDeclTag, uint> declTagToMethod = new Dictionary<MethodDeclTag, uint>(); uint methodIndex = 0; foreach (HighMethod method in m_methods) { if (declTagToMethod.ContainsKey(method.MethodDeclTag)) throw new Exception("Duplicate method declaration"); declTagToMethod.Add(method.MethodDeclTag, methodIndex++); } m_declTagToMethod = declTagToMethod; } m_declTagToVTableSlot = new Dictionary<MethodDeclTag, uint>(); m_ifcToIfcSlot = new Dictionary<TypeSpecClassTag, uint>(); List<CliVtableSlot> slots = new List<CliVtableSlot>(); if (m_parentClass != null) { foreach (KeyValuePair<MethodDeclTag, uint> dttvs in m_parentClass.m_declTagToVTableSlot) m_declTagToVTableSlot.Add(dttvs.Key, dttvs.Value); foreach (CliVtableSlot parentSlot in m_parentClass.m_vtable) { CliMethodIndex methodIndex = parentSlot.MethodIndex; if (methodIndex == null) slots.Add(parentSlot); else { CliMethodIndex newIndex = new CliMethodIndex(methodIndex.Depth + 1, methodIndex.Index); slots.Add(new CliVtableSlot(newIndex, parentSlot.MethodSignature, parentSlot.IsSealed)); } } } foreach (HighClassVtableSlot slot in replacedSlots) { uint index; if (!m_declTagToVTableSlot.TryGetValue(slot.SlotTag, out index)) throw new Exception("Unmatched vtable slot replacement"); CliVtableSlot existingSlot = slots[(int)index]; if (existingSlot.IsSealed) throw new Exception("Can't replace sealed vtable slot"); if (existingSlot.MethodSignature != slot.Signature) throw new Exception("VTable slot override signature doesn't match"); CliMethodIndex methodIndex = null; if (!slot.IsAbstract) { HighMethod method; methodIndex = this.FindMethod(slot.ImplementingMethodTag, out method); if (method.MethodSignature != slot.Signature) throw new Exception("Signature of method used by vtable slot doesn't match vtable slot's signature"); } slots[(int)index] = new CliVtableSlot(methodIndex, slot.Signature, slot.IsFinal); } foreach (HighClassVtableSlot slot in newSlots) { CliMethodIndex methodIndex = null; if (!slot.IsAbstract) { HighMethod method; methodIndex = this.FindMethod(slot.ImplementingMethodTag, out method); if (method.MethodSignature != slot.Signature) throw new Exception("Signature of method used by vtable slot doesn't match vtable slot's signature"); } m_declTagToVTableSlot.Add(slot.SlotTag, (uint)slots.Count); slots.Add(new CliVtableSlot(methodIndex, slot.Signature, slot.IsFinal)); } m_vtable = slots.ToArray(); if (!m_isAbstract) foreach (CliVtableSlot slot in m_vtable) if (slot.MethodIndex == null) throw new RpaCompileException("Non-abstract class has unoverrided abstract methods"); m_nameToInstanceFieldSlot = new Dictionary<string, uint>(); for (uint i = 0; i < m_instanceFields.Length; i++) { string fldName = m_instanceFields[i].Name; if (m_nameToInstanceFieldSlot.ContainsKey(fldName)) throw new RpaCompileException("Duplicate field name"); m_nameToInstanceFieldSlot.Add(fldName, i); } m_nameToStaticFieldSlot = new Dictionary<string, uint>(); for (uint i = 0; i < m_staticFields.Length; i++) { string fldName = m_staticFields[i].Name; if (m_nameToStaticFieldSlot.ContainsKey(fldName)) throw new RpaCompileException("Duplicate field name"); m_nameToStaticFieldSlot.Add(fldName, i); } HashSet<TypeSpecClassTag> explicitImpls = new HashSet<TypeSpecClassTag>(); List<CliInterfaceImpl> interfaceImpls = new List<CliInterfaceImpl>(); foreach (HighInterfaceImplementation ifcImpl in typeInterfaceImpls) { if (!explicitImpls.Add(ifcImpl.Interface)) throw new Exception("Duplicate interface implementation"); interfaceImpls.Add(ResolveInterfaceImpl(compiler, ifcImpl)); } m_interfaceImpls = interfaceImpls.ToArray(); m_parentClassSpec = parentClassSpec; m_explicitInterfaceSpecs = typeDef.ParentInterfaces; if (m_explicitInterfaceSpecs == null) m_explicitInterfaceSpecs = new TypeSpecClassTag[0]; List<TypeSpecTag> thisGenericParameters = new List<TypeSpecTag>(); for (uint i = 0; i < m_numGenericParameters; i++) { TypeSpecGenericParamTypeTag gptt = new TypeSpecGenericParamTypeTag(TypeSpecGenericParamTypeTag.Values.Var); TypeSpecGenericParamTag gpTag = new TypeSpecGenericParamTag(gptt, i); gpTag = (TypeSpecGenericParamTag)compiler.TagRepository.InternTypeSpec(gpTag); thisGenericParameters.Add(gpTag); } TypeSpecClassTag thisClass = new TypeSpecClassTag(m_typeName, thisGenericParameters.ToArray()); thisClass = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(thisClass); m_typeSpec = thisClass; m_typeDeclarationOrder = new Dictionary<TypeSpecClassTag, uint>(); ResolveTDOForClass(this); m_isCreated = true; return true; }