Exemple #1
0
        private MethodSpecTag ResolveVirtualMethod(Compiler compiler, CliClass cls, CliMethodIndex methodIndex)
        {
            uint depth = methodIndex.Depth;
            CliClass methodClass = cls;
            while (depth > 0)
            {
                methodClass = methodClass.ParentClass;
                depth--;
            }

            HighMethod method = methodClass.Methods[methodIndex.Index];
            if (method.IsStatic)
                throw new RpaCompileException("Vtable slot implementation is static");

            MethodSpecTag methodSpec = new MethodSpecTag(MethodSlotType.Instance, new TypeSpecTag[0], methodClass.TypeSpec, method.MethodDeclTag);
            return compiler.TagRepository.InternMethodSpec(methodSpec);
        }
Exemple #2
0
 public CliVtableSlot(CliVtableSlot baseSlot, Compiler compiler, TypeSpecTag[] argTypes)
 {
     m_methodIndex = baseSlot.m_methodIndex;
     m_isSealed = baseSlot.m_isSealed;
     m_methodSignature = baseSlot.m_methodSignature.Instantiate(compiler.TagRepository, argTypes);
 }
Exemple #3
0
        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;
        }
Exemple #4
0
 public CliVtableSlot(CliMethodIndex methodIndex, MethodSignatureTag methodSignature, bool isSealed)
 {
     m_methodIndex = methodIndex;
     m_isSealed = isSealed;
     m_methodSignature = methodSignature;
 }