예제 #1
0
        public CLRTypeSpec ArithPromoteValue(CLRTypeSpec typeSpec)
        {
            if (typeSpec.Equals(m_commonTypeLookup.I8)
                || typeSpec.Equals(m_commonTypeLookup.I16)
                || typeSpec.Equals(m_commonTypeLookup.I32)
                || typeSpec.Equals(m_commonTypeLookup.U8)
                || typeSpec.Equals(m_commonTypeLookup.U16)
                || typeSpec.Equals(m_commonTypeLookup.U32)
                || typeSpec.Equals(m_commonTypeLookup.Char)
                || typeSpec.Equals(m_commonTypeLookup.Boolean)
                )
                return m_commonTypeLookup.I32;
            if (typeSpec.Equals(m_commonTypeLookup.I64) || typeSpec.Equals(m_commonTypeLookup.U64))
                return m_commonTypeLookup.I64;
            if (typeSpec.Equals(m_commonTypeLookup.U) || typeSpec.Equals(m_commonTypeLookup.U))
                return m_commonTypeLookup.I;
            if (typeSpec.Equals(m_commonTypeLookup.F32))
                return m_commonTypeLookup.F32;
            if (typeSpec.Equals(m_commonTypeLookup.F64))
                return m_commonTypeLookup.F64;

            {
                CLRTypeSpec enumArithType = ResolveEnumArithType(typeSpec);
                if (enumArithType != null)
                    return ArithPromoteValue(enumArithType);
            }

            throw new ArgumentException();
        }
예제 #2
0
 public static VType.ValTypeEnum ValTypeForTypeSpec(CppBuilder cppBuilder, CLRTypeSpec typeSpec)
 {
     if (typeSpec is CLRTypeSpecClass)
     {
         CppClass cls = cppBuilder.GetCachedClass(typeSpec);
         if (cls.IsValueType)
             return VType.ValTypeEnum.ValueValue;
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecGenericInstantiation)
     {
         CLRTypeSpecGenericInstantiation giSpec = (CLRTypeSpecGenericInstantiation)typeSpec;
         CppClass cls = cppBuilder.GetCachedClass(new CLRTypeSpecClass(giSpec.GenericType.TypeDef));
         if (cls.IsValueType)
             return VType.ValTypeEnum.ValueValue;
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecSZArray)
     {
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecComplexArray)
     {
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecVarOrMVar)
     {
         // Generic parameters are always treated like value types even if they're provably ref types
         return VType.ValTypeEnum.ValueValue;
     }
     else
         throw new ArgumentException();
 }
예제 #3
0
파일: CppField.cs 프로젝트: elasota/clarity
 private CppField(CppField baseInstance, CLRTypeSpec[] typeParams, CLRTypeSpec[] methodParams)
 {
     Type = baseInstance.Type.Instantiate(typeParams, methodParams);
     OriginallyGenericParam = baseInstance.OriginallyGenericParam;
     Name = baseInstance.Name;
     Field = baseInstance.Field;
     DeclaredInClassSpec = baseInstance.DeclaredInClassSpec.Instantiate(typeParams, methodParams);
 }
예제 #4
0
 public int AllocStaticToken(CLRTypeSpec typeSpecArg)
 {
     for (int i = 0; i < m_staticInitTokens.Count; i++)
     {
         if (m_staticInitTokens[i].Equals(typeSpecArg))
             return i;
     }
     m_staticInitTokens.Add(typeSpecArg);
     return m_staticInitTokens.Count - 1;
 }
예제 #5
0
 public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, SsaRegister regArg2, string strArg, CLRTypeSpec typeSpecArg, CLRTypeSpec typeSpecArg2)
 {
     Opcode = opcode;
     CodeLocation = codeLocation;
     RegArg = regArg;
     RegArg2 = regArg2;
     StrArg = strArg;
     TypeSpecArg = typeSpecArg;
     TypeSpecArg2 = typeSpecArg2;
 }
예제 #6
0
 public void Add(CLRTypeSpec typeSpec)
 {
     CppMangleBuilder builder = new CppMangleBuilder();
     if (typeSpec is CLRTypeSpecClass)
     {
         CLRTypeSpecClass cls = (CLRTypeSpecClass)typeSpec;
         builder.Add("class");
         builder.Add(cls.TypeDef);
     }
     else if (typeSpec is CLRTypeSpecGenericInstantiation)
     {
         CLRTypeSpecGenericInstantiation gi = (CLRTypeSpecGenericInstantiation)typeSpec;
         builder.Add("gi");
         builder.Add(gi.GenericType);
         builder.Add(gi.ArgTypes.Length);
         foreach (CLRTypeSpec argType in gi.ArgTypes)
             builder.Add(argType);
     }
     else if (typeSpec is CLRTypeSpecVoid)
     {
         builder.Add("void");
     }
     else if (typeSpec is CLRTypeSpecSZArray)
     {
         builder.Add("szarray");
         builder.Add(((CLRTypeSpecSZArray)typeSpec).SubType);
     }
     else if (typeSpec is CLRTypeSpecComplexArray)
     {
         builder.Add("complexarray");
         CLRTypeSpecComplexArray cplxArray = (CLRTypeSpecComplexArray)typeSpec;
         builder.Add(cplxArray.SubType);
         builder.Add((int)cplxArray.Rank);
         for (uint i = 0; i < cplxArray.Rank; i++)
             builder.Add(cplxArray.LowBounds[i]);
     }
     else if (typeSpec is CLRTypeSpecVarOrMVar)
     {
         CLRTypeSpecVarOrMVar varOrMVar = (CLRTypeSpecVarOrMVar)typeSpec;
         builder.Add("varOrMVar");
         builder.Add((int)varOrMVar.ElementType);
         builder.Add((int)varOrMVar.Value);
     }
     else
         throw new ParseFailedException("Strange type spec");
     AddBytes(builder.FinishAsBytes());
 }
예제 #7
0
        public CLRTypeSpec ArithConvergeValues(CLRTypeSpec ts1, CLRTypeSpec ts2)
        {
            // Both are value types, so these must converge
            CLRTypeSpec promoted1 = ArithPromoteValue(ts1);
            CLRTypeSpec promoted2 = ArithPromoteValue(ts2);

            // If both promote to the same thing, use that
            if (promoted1.Equals(promoted2))
                return promoted1;

            if (promoted1.Equals(m_commonTypeLookup.I32) && promoted2.Equals(m_commonTypeLookup.I64))
                return m_commonTypeLookup.I64;
            if (promoted1.Equals(m_commonTypeLookup.I64) && promoted2.Equals(m_commonTypeLookup.I32))
                return m_commonTypeLookup.I64;
            if (promoted1.Equals(m_commonTypeLookup.F32) && promoted2.Equals(m_commonTypeLookup.F64))
                return m_commonTypeLookup.F64;
            if (promoted1.Equals(m_commonTypeLookup.F64) && promoted2.Equals(m_commonTypeLookup.F32))
                return m_commonTypeLookup.F64;

            // Unmergable
            throw new ArgumentException();
        }
예제 #8
0
        public CLRTypeSpec FindCommonBase(CLRTypeSpec typeSpec1, CLRTypeSpec typeSpec2)
        {
            CLRTypeSpec trace1 = TranslateToRootClass(typeSpec1);
            CLRTypeSpec trace2 = TranslateToRootClass(typeSpec2);

            HashSet<CLRTypeSpec> root1hierarchy = new HashSet<CLRTypeSpec>();
            while (trace1 != null)
            {
                root1hierarchy.Add(trace1);
                CppClass cls = m_builder.GetCachedClass(trace1);
                trace1 = cls.ParentTypeSpec;
            }

            while (trace2 != null)
            {
                if (root1hierarchy.Contains(trace2))
                    return trace2;
                CppClass cls = m_builder.GetCachedClass(trace2);
                trace2 = cls.ParentTypeSpec;
            }

            throw new ArgumentException();
        }
예제 #9
0
파일: CppClass.cs 프로젝트: elasota/clarity
        private CppClass(CppClass baseInstance, CLRTypeSpec[] typeParams, CLRTypeSpec[] methodParams)
        {
            if (typeParams.Length != baseInstance.NumGenericParameters)
                throw new ArgumentException();

            m_methods = new List<CppMethod>();
            m_fields = new List<CppField>();
            m_allVtableSlots = new List<CppVtableSlot>();
            m_overrideVisibleVtableSlots = new List<CppVtableSlot>();
            m_newImplementationVisibleVtableSlots = new List<CppVtableSlot>();
            m_inheritedFields = new List<CppField>();
            m_reimplementedInterfaces = new List<CLRTypeSpec>();
            m_newlyImplementedInterfaces = new List<CLRTypeSpec>();
            m_explicitInterfaces = new List<CLRTypeSpec>();
            m_inheritedImplementedInterfaces = new List<CLRTypeSpec>();
            m_passiveIfcConversions = new List<CLRTypeSpec>();
            m_inheritedPassiveIfcConversions = new List<CLRTypeSpec>();
            m_genericParameters = new List<CLRTypeSpec>();

            m_typeDef = baseInstance.m_typeDef;

            Name = baseInstance.Name;
            FullName = baseInstance.FullName;
            if (baseInstance.ParentTypeSpec != null)
                ParentTypeSpec = baseInstance.ParentTypeSpec.Instantiate(typeParams, methodParams);

            NumGenericParameters = baseInstance.NumGenericParameters;
            m_genericParameters.AddRange(typeParams);

            foreach (CppMethod method in baseInstance.m_methods)
                m_methods.Add(method.Instantiate(typeParams, methodParams));
            foreach (CppField field in baseInstance.m_fields)
                m_fields.Add(field.Instantiate(typeParams, methodParams));

            foreach (CppVtableSlot vts in baseInstance.m_overrideVisibleVtableSlots)
                m_overrideVisibleVtableSlots.Add(vts.Instantiate(typeParams, methodParams));
            foreach (CppVtableSlot vts in baseInstance.m_newImplementationVisibleVtableSlots)
                m_newImplementationVisibleVtableSlots.Add(vts.Instantiate(typeParams, methodParams));
            foreach (CppVtableSlot vts in baseInstance.m_allVtableSlots)
                m_allVtableSlots.Add(vts.Instantiate(typeParams, methodParams));

            foreach (CppField field in baseInstance.m_inheritedFields)
                m_inheritedFields.Add(field.Instantiate(typeParams, methodParams));
            foreach (CLRTypeSpec impl in baseInstance.m_newlyImplementedInterfaces)
                m_newlyImplementedInterfaces.Add(impl.Instantiate(typeParams, methodParams));
            foreach (CLRTypeSpec impl in baseInstance.m_explicitInterfaces)
                m_explicitInterfaces.Add(impl.Instantiate(typeParams, methodParams));
            foreach (CLRTypeSpec impl in baseInstance.m_reimplementedInterfaces)
                m_reimplementedInterfaces.Add(impl.Instantiate(typeParams, methodParams));
            foreach (CLRTypeSpec impl in baseInstance.m_inheritedImplementedInterfaces)
                m_inheritedImplementedInterfaces.Add(impl.Instantiate(typeParams, methodParams));
            foreach (CLRTypeSpec impl in baseInstance.m_passiveIfcConversions)
                m_passiveIfcConversions.Add(impl.Instantiate(typeParams, methodParams));
            foreach (CLRTypeSpec impl in baseInstance.m_inheritedPassiveIfcConversions)
                m_inheritedPassiveIfcConversions.Add(impl.Instantiate(typeParams, methodParams));

            IsDelegate = baseInstance.IsDelegate;
            IsMulticastDelegate = baseInstance.IsMulticastDelegate;
            IsEnum = baseInstance.IsEnum;
            IsValueType = baseInstance.IsValueType;
            if (DelegateSignature != null)
                DelegateSignature = baseInstance.DelegateSignature.Instantiate(typeParams, methodParams);
            HaveNewStaticFields = baseInstance.HaveNewStaticFields;
            HaveInheritedStaticFields = baseInstance.HaveInheritedStaticFields;
            HaveAnyGenericMethods = baseInstance.HaveAnyGenericMethods;
            StubPath = null;
        }
예제 #10
0
파일: CppClass.cs 프로젝트: elasota/clarity
        private void AddPassiveConversion(CLRTypeSpec ifcTypeSpec)
        {
            bool isMatch = false;
            foreach (CLRTypeSpec ifc in m_passiveIfcConversions)
            {
                if (ifc.Equals(ifcTypeSpec))
                {
                    isMatch = true;
                    break;
                }
            }
            if (!isMatch)
            {
                foreach (CLRTypeSpec ifc in m_inheritedPassiveIfcConversions)
                {
                    if (ifc.Equals(ifcTypeSpec))
                    {
                        isMatch = true;
                        break;
                    }
                }
            }

            if (!isMatch)
                m_passiveIfcConversions.Add(ifcTypeSpec);
        }
예제 #11
0
파일: CppClass.cs 프로젝트: elasota/clarity
        public void ResolveInherit(CppBuilder builder, CppClass parentClass, IEnumerable<CLRTypeSpec> interfaces, CLRTypeSpec parentTypeSpec)
        {
            // There are a LOT of tricky slotting cases here.
            // See TestNewSlotImplementation, TestSlotDivergence, and TestImplementNonVirtual for some sample cases.
            //
            // Roughly how this works:
            // 1.) Override vtable slots based on matching:
            //     - If a method is ReuseSlot, then it overrides a slot no matter what
            //     - If a method is NewSlot, then it creates a slot
            // 2.) Implement MethodImpls and interfaces as cross-slot thunks
            //
            // Two notable complications with this:
            //
            // In Clarity, we only implement the specified interface once in a given class's heirarchy, but
            // reimplemented interfaces need to emit new mappings because the reimplementation can change how the
            // interface is implemented.  For example, if a parent class implements an interface method by match,
            // and then a derived class hides that method with a newslot and reimplements the interface, then the
            // interface must link to the newslot method.
            //
            // This is further complicated by the II.12.2 dispatch rules, which have errors.
            //
            // We might be able to optimize this a bit if we can detect that a method reimplementation is the
            // same as the one that already exists.
            //
            // The second complication is that Roslyn sometimes emits useless but apparently legal .override
            // directives that "override" a parent class implementation with the same method that already overrides
            // it from reuseslot matching.

            ParentTypeSpec = parentTypeSpec;

            if (parentClass != null)
            {
                m_allVtableSlots.AddRange(parentClass.m_allVtableSlots);

                List<CppVtableSlot> parentOverrideVisibleSlots = new List<CppVtableSlot>(parentClass.m_overrideVisibleVtableSlots);

                foreach (CppMethod method in m_methods)
                {
                    if (method.Virtual)
                    {
                        if (method.CreatesSlot != null)
                            RemoveOverrides(parentOverrideVisibleSlots, method.CreatesSlot);

                        if (method.Overrides)
                        {
                            List<int> overrideIndexes = FindOverrideIndexes(parentOverrideVisibleSlots, method.Name, method.MethodSignature);
                            if (overrideIndexes.Count != 1)
                                throw new ParseFailedException("Method did not override exactly one slot");
                            method.ReplacesStandardSlot = parentOverrideVisibleSlots[overrideIndexes[0]];
                        }
                    }
                }

                if (m_newImplementationVisibleVtableSlots.Count != 0)
                    throw new Exception();

                foreach (CppMethod method in m_methods)
                {
                    if (method.Virtual && method.MethodDef.MemberAccess == CLRMethodDefRow.MethodMemberAccess.Public)
                    {
                        if (method.Overrides)
                            m_newImplementationVisibleVtableSlots.Add(method.ReplacesStandardSlot);
                        else
                            m_newImplementationVisibleVtableSlots.Add(method.CreatesSlot);
                    }
                }

                m_overrideVisibleVtableSlots.AddRange(parentOverrideVisibleSlots);
            }

            if (parentClass != null)
            {
                // Remove already-implemented interfaces from this class's set, but keep reimplementations
                // to resolve them again
                List<CLRTypeSpec> dedupedInterfaces = new List<CLRTypeSpec>();
                List<CLRTypeSpec> reimplementedInterfaces = new List<CLRTypeSpec>();
                List<CLRTypeSpec> allInheritedInterfaces = new List<CLRTypeSpec>();

                allInheritedInterfaces.AddRange(parentClass.m_newlyImplementedInterfaces);
                allInheritedInterfaces.AddRange(parentClass.m_inheritedImplementedInterfaces);
                foreach (CLRTypeSpec ifc in m_newlyImplementedInterfaces)
                {
                    if (allInheritedInterfaces.Contains(ifc))
                        reimplementedInterfaces.Add(ifc);
                    else
                        dedupedInterfaces.Add(ifc);
                }

                m_newlyImplementedInterfaces = dedupedInterfaces;
                m_reimplementedInterfaces = reimplementedInterfaces;

                m_inheritedFields.AddRange(parentClass.m_inheritedFields);
                m_inheritedFields.AddRange(parentClass.m_fields);

                m_inheritedImplementedInterfaces = allInheritedInterfaces;

                m_inheritedPassiveIfcConversions.AddRange(parentClass.m_passiveIfcConversions);
                m_inheritedPassiveIfcConversions.AddRange(parentClass.m_inheritedPassiveIfcConversions);

                IsValueType = (parentClass.FullName == "System.ValueType" && this.FullName != "System.Enum") || parentClass.FullName == "System.Enum";
                IsEnum = parentClass.FullName == "System.Enum";

                IsMulticastDelegate = (parentClass.FullName == "System.MulticastDelegate");
                IsDelegate = IsMulticastDelegate || (parentClass.FullName == "System.Delegate" && this.FullName != "System.MulticastDelegate");
                HaveInheritedStaticFields = (parentClass.HaveInheritedStaticFields || parentClass.HaveNewStaticFields);

                if (IsDelegate)
                {
                    foreach (CppMethod method in m_methods)
                    {
                        if (method.Name == "Invoke")
                        {
                            DelegateSignature = method.MethodSignature;
                            break;
                        }
                    }

                    if (DelegateSignature == null)
                        throw new ParseFailedException("Malformed delegate");
                }
            }
        }
예제 #12
0
        private bool WriteSignatureMatchedBinding(HighFileBuilder fileBuilder, BinaryWriter writer, CppClass cls, CppVtableSlot ifcSlot, CLRTypeSpec ifcTypeSpec)
        {
            bool haveMatch = false;
            foreach (CppVtableSlot vtSlot in cls.NewImplementationVisibleVtableSlots)
            {
                if (ifcSlot.Name == vtSlot.Name && ifcSlot.Signature.Equals(vtSlot.Signature))
                {
                    if (haveMatch)
                    {
                        Console.WriteLine("WARNING: Class " + cls.FullName + " has multiple matches for the same interface implementation");
                        break;
                    }
                    haveMatch = true;

                    writer.Write(true);    // HACK - FIXME
                    WriteInterfaceBinding(fileBuilder, writer, ifcSlot, vtSlot);
                }
            }

            if (haveMatch == true)
                return true;

            CLRTypeSpec parentSpec = cls.ParentTypeSpec;
            if (parentSpec == null)
                return false;

            CppClass parentClass = GetCachedClass(parentSpec);

            // Look for prior implementations of this interface, if any are found, STOP and return no-match.
            // See TestInheritedImplementationDeprioritization.  Matches are only recorded if they're new.
            foreach (CLRTypeSpec ifc in parentClass.NewlyImplementedInterfaces)
                if (ifc.Equals(ifcTypeSpec))
                    return false;
            foreach (CLRTypeSpec ifc in parentClass.ReimplementedInterfaces)
                if (ifc.Equals(ifcTypeSpec))
                    return false;
            return WriteSignatureMatchedBinding(fileBuilder, writer, parentClass, ifcSlot, ifcTypeSpec);
        }
예제 #13
0
        private bool IsProvablyReferenceType(CLRTypeSpec typeSpec)
        {
            if (typeSpec is CLRTypeSpecClass || typeSpec is CLRTypeSpecGenericInstantiation)
                return !m_builder.GetCachedClass(typeSpec).IsValueType;
            else if (typeSpec is CLRTypeSpecComplexArray || typeSpec is CLRTypeSpecSZArray)
                return true;
            else if (typeSpec is CLRTypeSpecVarOrMVar)
            {
                CLRGenericParamRow genericParam = GenericParamForSpec((CLRTypeSpecVarOrMVar)typeSpec);

                if (genericParam.ReferenceTypeConstraint)
                    return true;

                if (genericParam.NotNullableValueTypeConstraint)
                    return false;

                // Look for a non-interface class constraint
                // If one exists, then this is a reference type
                foreach (CLRGenericParamConstraintRow constraint in genericParam.Constraints)
                {
                    CLRTypeSpec constraintType = m_builder.Assemblies.InternTypeDefOrRefOrSpec(constraint.Constraint);
                    CppClass constraintClass = m_builder.GetCachedClass(constraintType);
                    if (constraintClass.TypeDef.Semantics == CLRTypeDefRow.TypeSemantics.Interface)
                        continue;
                    return true;
                }

                // Found nothing, this could be a reference or value type
                return false;
            }

            throw new ArgumentException();
        }
예제 #14
0
 private MidInstruction.ArithEnum ArithModeForUnaryOp(CLRTypeSpec ts)
 {
     // III.6
     if (ts.Equals(m_commonTypeLookup.I32))
         return MidInstruction.ArithEnum.ArithType_Int32;
     if (ts.Equals(m_commonTypeLookup.I64))
         return MidInstruction.ArithEnum.ArithType_Int64;
     if (ts.Equals(m_commonTypeLookup.F32))
         return MidInstruction.ArithEnum.ArithType_Float32;
     if (ts.Equals(m_commonTypeLookup.F64))
         return MidInstruction.ArithEnum.ArithType_Float64;
     if (ts.Equals(m_commonTypeLookup.I))
         return MidInstruction.ArithEnum.ArithType_NativeInt;
     throw new ArgumentException();
 }
예제 #15
0
        private bool IsClassBasedOn(CppClass cls, CLRTypeSpec to)
        {
            foreach (CLRTypeSpec newIfc in cls.NewlyImplementedInterfaces)
            {
                if (IsGenericVariantAssignableTo(newIfc, to))
                    return true;
            }

            if (cls.ParentTypeSpec == null)
                return false;

            if (cls.ParentTypeSpec.Equals(to))
                return true;

            return IsClassBasedOn(m_builder.GetCachedClass(cls.ParentTypeSpec), to);
        }
예제 #16
0
        public CLRTypeSpec ResolveEnumArithType(CLRTypeSpec typeSpec)
        {
            if (!(typeSpec is CLRTypeSpecClass))
                return null;

            CLRTypeDefRow typeDef = ((CLRTypeSpecClass)typeSpec).TypeDef;
            if (typeDef.Extends == null)
                return null;

            CLRTypeSpec extendsSpec = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec(typeDef.Extends);
            if (!(extendsSpec is CLRTypeSpecClass))
                return null;

            CLRTypeDefRow extendsDef = ((CLRTypeSpecClass)extendsSpec).TypeDef;
            if (extendsDef.ContainerClass != null || extendsDef.TypeNamespace != "System" || extendsDef.TypeName != "Enum")
                return null;

            foreach (CLRFieldRow field in typeDef.Fields)
            {
                if (!field.Static)
                    return m_cppBuilder.Assemblies.InternVagueType(field.Signature.Type);
            }
            return null;
        }
예제 #17
0
 private static MidInstruction.ArithEnum ArithModeForShiftOp(CommonTypeLookup lookup, CLRTypeSpec ls, CLRTypeSpec rs)
 {
     // III.6
     if (ls.Equals(lookup.I32))
     {
         if (rs.Equals(lookup.I32))
             return MidInstruction.ArithEnum.ArithType_Int32;
         throw new ArgumentException();
     }
     if (ls.Equals(lookup.I64))
     {
         if (rs.Equals(lookup.I64))
             return MidInstruction.ArithEnum.ArithType_Int64;
         if (rs.Equals(lookup.I))
             return MidInstruction.ArithEnum.ArithType_Int64;
         throw new ArgumentException();
     }
     if (ls.Equals(lookup.I))
     {
         if (rs.Equals(lookup.I64))
             return MidInstruction.ArithEnum.ArithType_NativeInt;
         if (rs.Equals(lookup.I))
             return MidInstruction.ArithEnum.ArithType_NativeInt;
         throw new ArgumentException();
     }
     throw new ArgumentException();
 }
예제 #18
0
 public static TypeSpecTag CreateTypeTag(CLRTypeSpec typeSpec)
 {
     if (typeSpec is CLRTypeSpecClass)
     {
         CLRTypeSpecClass classSpec = (CLRTypeSpecClass)typeSpec;
         return new TypeSpecClassTag(CreateTypeNameTag(classSpec.TypeDef), new TypeSpecTag[0]);
     }
     else if (typeSpec is CLRTypeSpecComplexArray)
     {
         CLRTypeSpecComplexArray complexArraySpec = (CLRTypeSpecComplexArray)typeSpec;
         return new TypeSpecArrayTag(complexArraySpec.Rank, CreateTypeTag(complexArraySpec.SubType));
     }
     else if (typeSpec is CLRTypeSpecGenericInstantiation)
     {
         CLRTypeSpecGenericInstantiation genericInstTag = (CLRTypeSpecGenericInstantiation)typeSpec;
         List<TypeSpecTag> argTypes = new List<TypeSpecTag>();
         foreach (CLRTypeSpec argType in genericInstTag.ArgTypes)
             argTypes.Add(CreateTypeTag(argType));
         return new TypeSpecClassTag(CreateTypeNameTag(genericInstTag.GenericType.TypeDef), argTypes.ToArray());
     }
     else if (typeSpec is CLRTypeSpecSZArray)
     {
         CLRTypeSpecSZArray szArraySpec = (CLRTypeSpecSZArray)typeSpec;
         return new TypeSpecArrayTag(1, CreateTypeTag(szArraySpec.SubType));
     }
     else if (typeSpec is CLRTypeSpecVarOrMVar)
     {
         CLRTypeSpecVarOrMVar varOrMVarSpec = (CLRTypeSpecVarOrMVar)typeSpec;
         TypeSpecGenericParamTypeTag v;
         switch (varOrMVarSpec.ElementType)
         {
             case CLRSigType.ElementType.VAR:
                 v = new TypeSpecGenericParamTypeTag(TypeSpecGenericParamTypeTag.Values.Var);
                 break;
             case CLRSigType.ElementType.MVAR:
                 v = new TypeSpecGenericParamTypeTag(TypeSpecGenericParamTypeTag.Values.MVar);
                 break;
             default:
                 throw new Exception("Unrecognized VarOrMVar type");
         }
         return new TypeSpecGenericParamTag(v, varOrMVarSpec.Value);
     }
     else if (typeSpec is CLRTypeSpecVoid)
     {
         return new TypeSpecVoidTag();
     }
     else
         throw new Exception("Unrecognized type spec");
 }
예제 #19
0
        public CppTraceabilityEnum GetCachedTraceability(CLRTypeSpec typeSpec)
        {
            if (typeSpec is CLRTypeSpecComplexArray ||
                typeSpec is CLRTypeSpecSZArray)
                return CppTraceabilityEnum.DefinitelyTraced;

            if (typeSpec is CLRTypeSpecVarOrMVar)
            {
                // TODO: Maybe promote this to DefinitelyTraced by checking constraints
                return CppTraceabilityEnum.MaybeTraced;
            }

            if (typeSpec is CLRTypeSpecClass || typeSpec is CLRTypeSpecGenericInstantiation)
            {
                CppClass cls = GetCachedClass(typeSpec);
                if (!cls.IsValueType)
                    return CppTraceabilityEnum.DefinitelyTraced;

                bool maybeTraceable = false;
                foreach (CppField field in cls.Fields)
                {
                    if (field.Field.Static)
                        continue;

                    CppTraceabilityEnum fieldTraceability = GetCachedTraceability(field.Type);
                    if (fieldTraceability == CppTraceabilityEnum.DefinitelyTraced)
                        return CppTraceabilityEnum.DefinitelyTraced;
                    if (fieldTraceability == CppTraceabilityEnum.MaybeTraced)
                        maybeTraceable = true;
                }

                if (maybeTraceable)
                    return CppTraceabilityEnum.MaybeTraced;
                return CppTraceabilityEnum.NotTraced;
            }

            throw new ArgumentException();
        }
예제 #20
0
        private bool FieldNeedsDependencyDefs(CLRTypeSpec typeSpec)
        {
            if (typeSpec is CLRTypeSpecComplexArray ||
                typeSpec is CLRTypeSpecSZArray)
                return false;

            if (typeSpec is CLRTypeSpecVarOrMVar)
                return false;

            if (typeSpec is CLRTypeSpecClass || typeSpec is CLRTypeSpecGenericInstantiation)
            {
                CppClass cls = GetCachedClass(typeSpec);
                return cls.IsValueType;
            }

            throw new ArgumentException();
        }
예제 #21
0
        private SsaRegister EmitPassiveConversion(Clarity.Rpa.CodeLocationTag codeLocation, SsaRegister sourceReg, CLRTypeSpec destType, CppCfgNodeOutline outline, IList<Clarity.Rpa.HighInstruction> instrs)
        {
            if (sourceReg.VType.ValType == VType.ValTypeEnum.DelegateSimpleMethod ||
                sourceReg.VType.ValType == VType.ValTypeEnum.DelegateVirtualMethod)
                return sourceReg;

            if (sourceReg.VType.TypeSpec.Equals(destType))
                return sourceReg;

            if (sourceReg.VType.ValType == VType.ValTypeEnum.Null)
            {
                SsaRegister nullReg = new SsaRegister(new VType(VType.ValTypeEnum.Null, destType));
                nullReg.MakeUsable();
                nullReg.GenerateUniqueID(m_regAllocator);

                outline.AddRegister(nullReg);
                return nullReg;
            }

            SsaRegister newReg;
            switch (sourceReg.VType.ValType)
            {
                case VType.ValTypeEnum.ConstantReference:
                case VType.ValTypeEnum.ReferenceValue:
                    newReg = new SsaRegister(new VType(VType.ValTypeEnum.ReferenceValue, destType));
                    break;
                case VType.ValTypeEnum.ValueValue:
                case VType.ValTypeEnum.ConstantValue:
                    newReg = new SsaRegister(new VType(VType.ValTypeEnum.ValueValue, destType));
                    break;
                default:
                    throw new ArgumentException();
            }

            newReg.MakeUsable();
            newReg.GenerateUniqueID(m_regAllocator);

            instrs.Add(new Clarity.Rpa.Instructions.PassiveConvertInstruction(
                codeLocation,
                InternSsaRegister(newReg),
                InternSsaRegister(sourceReg)
                ));

            return newReg;
        }
예제 #22
0
        public CppClass GetCachedClass(CLRTypeSpec typeSpec)
        {
            CppClass cls;
            if (m_typeSpecClasses.TryGetValue(typeSpec, out cls))
                return cls;

            cls = CreateClassFromType(typeSpec);
            m_typeSpecClasses.Add(typeSpec, cls);
            return cls;
        }
예제 #23
0
 private SsaRegister EmitPassiveConversion_PermitRefs(Clarity.Rpa.CodeLocationTag codeLocation, SsaRegister sourceReg, CLRTypeSpec destType, CppCfgNodeOutline outline, IList<Clarity.Rpa.HighInstruction> instrs)
 {
     switch (sourceReg.VType.ValType)
     {
         case VType.ValTypeEnum.ManagedPtr:
             if (sourceReg.VType.TypeSpec.Equals(destType))
                 return sourceReg;
             throw new ArgumentException();
         default:
             return EmitPassiveConversion(codeLocation, sourceReg, destType, outline, instrs);
     }
 }
예제 #24
0
        public CppClass CreateClassFromType(CLRTypeSpec typeSpec)
        {
            if (typeSpec is CLRTypeSpecClass)
            {
                // TODO: Check typedef premades
                CLRTypeSpecClass tsClass = (CLRTypeSpecClass)typeSpec;
                CLRTypeDefRow typeDef = tsClass.TypeDef;

                CppClass cls = new CppClass(tsClass);
                foreach (CLRFieldRow fieldRow in typeDef.Fields)
                    cls.AddField(m_assemblies, fieldRow);
                foreach (CLRMethodDefRow methodRow in typeDef.MethodDefs)
                    cls.AddMethod(m_assemblies, methodRow);

                CppClass parentClass = null;
                CLRTypeSpec parentTypeSpec = null;
                if (typeDef.Extends != null)
                {
                    parentTypeSpec = m_assemblies.InternTypeDefOrRefOrSpec(typeDef.Extends);
                    parentClass = GetCachedClass(parentTypeSpec);
                }

                List<CLRTypeSpec> interfaces = new List<CLRTypeSpec>();

                foreach (CLRTableRow ii in typeDef.ImplementedInterfaces)
                {
                    CLRTypeSpec ifc = m_assemblies.InternTypeDefOrRefOrSpec(ii);
                    cls.AddExplicitInterface(this, ifc);
                    interfaces.Add(ifc);
                }
                cls.ResolveInherit(this, parentClass, interfaces, parentTypeSpec);

                return cls;
            }
            else if (typeSpec is CLRTypeSpecGenericInstantiation)
            {
                CLRTypeSpecGenericInstantiation gi = (CLRTypeSpecGenericInstantiation)typeSpec;
                CppClass baseClass = GetCachedClass(gi.GenericType);
                return baseClass.Instantiate(gi.ArgTypes, null);
            }
            else
                throw new NotImplementedException();
        }
예제 #25
0
        private bool IsGenericVariantAssignableTo(CLRTypeSpec from, CLRTypeSpec to)
        {
            if (from.Equals(to))
                return true;

            CLRTypeSpecGenericInstantiation fromGI = from as CLRTypeSpecGenericInstantiation;
            CLRTypeSpecGenericInstantiation toGI = to as CLRTypeSpecGenericInstantiation;

            if (fromGI == null || toGI == null)
                return false;

            CLRTypeDefRow typeDef = fromGI.GenericType.TypeDef;
            if (typeDef != toGI.GenericType.TypeDef)
                return false;

            if (typeDef.Semantics != CLRTypeDefRow.TypeSemantics.Interface)
            {
                if (typeDef.Semantics != CLRTypeDefRow.TypeSemantics.Class)
                    throw new ArgumentException();

                CppClass cls = m_builder.GetCachedClass(from);
                if (!cls.IsDelegate)
                    return false;
            }

            int numParams = typeDef.GenericParameters.Length;
            for (int i = 0; i < numParams; i++)
            {
                CLRTypeSpec fromParam = fromGI.ArgTypes[i];
                CLRTypeSpec toParam = fromGI.ArgTypes[i];
                CLRGenericParamRow genericParam = typeDef.GenericParameters[i];

                if (fromParam.Equals(toParam))
                    continue;

                switch (genericParam.Variance)
                {
                    case CLRGenericParamRow.VarianceEnum.None:
                        // Invariant: Can't assign at all
                        return false;
                    case CLRGenericParamRow.VarianceEnum.Covariant:
                        if (!IsProvablyReferenceType(fromParam) || !IsProvablyReferenceType(toParam) || !IsRefAssignable(fromParam, toParam))
                            return false;
                        break;
                    case CLRGenericParamRow.VarianceEnum.Contravariant:
                        if (!IsProvablyReferenceType(fromParam) || !IsProvablyReferenceType(toParam) || !IsRefAssignable(toParam, fromParam))
                            return false;
                        break;
                    default:
                        throw new ArgumentException();
                }
            }

            return true;
        }
예제 #26
0
파일: CppClass.cs 프로젝트: elasota/clarity
        // IMPORTANT: This must match "type declaration order" in the spec.
        // Clarity doesn't implement TDO itself, it depends on the new interfaces list being in TDO.
        public void AddExplicitInterface(CppBuilder builder, CLRTypeSpec ifcTypeSpec)
        {
            CppClass ifcType = builder.GetCachedClass(ifcTypeSpec);

            // CS0695 guarantees that type substitution will never result in multiple interfaces
            // resolving to the same passive conversion, so this strategy should be OK
            m_explicitInterfaces.Add(ifcTypeSpec);

            // NOTE: This function is called BEFORE inheritance resolution, which may remove some newly implemented
            // interfaces and convert them to reimplemented.
            foreach (CLRTypeSpec ifc in ifcType.m_newlyImplementedInterfaces)
                AddExplicitInterface(builder, ifc);

            // Only add each explicit interface once
            foreach (CLRTypeSpec ifc in m_newlyImplementedInterfaces)
                if (ifc.Equals(ifcTypeSpec))
                    return;

            // Unique, add it
            m_newlyImplementedInterfaces.Add(ifcTypeSpec);
        }
예제 #27
0
        private CLRTypeSpec TranslateToRootClass(CLRTypeSpec typeSpec)
        {
            if (typeSpec is CLRTypeSpecClass || typeSpec is CLRTypeSpecGenericInstantiation)
                return typeSpec;
            else if (typeSpec is CLRTypeSpecComplexArray || typeSpec is CLRTypeSpecSZArray)
                return m_commonTypes.Array;
            else if (typeSpec is CLRTypeSpecVarOrMVar)
            {
                CLRGenericParamRow genericParam = GenericParamForSpec((CLRTypeSpecVarOrMVar)typeSpec);

                if (genericParam.NotNullableValueTypeConstraint)
                    return m_commonTypes.ValueType;

                foreach (CLRGenericParamConstraintRow constraint in genericParam.Constraints)
                {
                    CLRTypeSpec constraintType = m_builder.Assemblies.InternTypeDefOrRefOrSpec(constraint.Constraint);
                    CppClass constraintClass = m_builder.GetCachedClass(constraintType);
                    if (constraintClass.TypeDef.Semantics == CLRTypeDefRow.TypeSemantics.Interface)
                        continue;
                    return constraintType;
                }

                return m_commonTypes.Object;
            }

            throw new ArgumentException();
        }
예제 #28
0
파일: CppClass.cs 프로젝트: elasota/clarity
 public CppClass Instantiate(CLRTypeSpec[] typeParams, CLRTypeSpec[] methodParams)
 {
     return new CppClass(this, typeParams, methodParams);
 }
예제 #29
0
        public bool IsRefAssignable(CLRTypeSpec from, CLRTypeSpec to)
        {
            if (from.Equals(to))
                return true;

            if (from is CLRTypeSpecClass)
            {
                CppClass fromClass = m_builder.GetCachedClass(from);
                return IsClassBasedOn(fromClass, to);
            }
            else if (from is CLRTypeSpecGenericInstantiation)
            {
                CppClass fromClass = m_builder.GetCachedClass(from);
                if (fromClass.IsDelegate || fromClass.TypeDef.Semantics == CLRTypeDefRow.TypeSemantics.Interface)
                {
                    if (IsGenericVariantAssignableTo(from, to))
                        return true;
                }
                if (IsClassBasedOn(fromClass, to))
                    return true;
                if (to.Equals(m_commonTypes.Object))
                    return true;
                return false;
            }
            else if (from is CLRTypeSpecComplexArray)
            {
                if (!(to is CLRTypeSpecComplexArray))
                    return IsRefAssignable(m_commonTypes.Array, to);

                CLRTypeSpecComplexArray cplxFrom = (CLRTypeSpecComplexArray)from;
                CLRTypeSpecComplexArray cplxTo = (CLRTypeSpecComplexArray)to;

                if (cplxFrom.Rank != cplxTo.Rank)
                    return false;

                for (uint i = 0; i < cplxFrom.Rank; i++)
                    if (cplxFrom.LowBounds[i] != cplxTo.LowBounds[i])
                        return false;

                CLRTypeSpec subscriptFrom = cplxFrom.SubType;
                CLRTypeSpec subscriptTo = cplxTo.SubType;

                if (IsProvablyReferenceType(subscriptFrom))
                    return IsRefAssignable(subscriptFrom, subscriptTo);
                return subscriptFrom.Equals(subscriptTo);
            }
            else if (from is CLRTypeSpecSZArray)
            {
                if (IsRefAssignable(m_commonTypes.Array, to))
                    return true;

                if (!(to is CLRTypeSpecSZArray))
                    return false;

                CLRTypeSpecSZArray arrayFrom = (CLRTypeSpecSZArray)from;
                CLRTypeSpecSZArray arrayTo = (CLRTypeSpecSZArray)to;

                CLRTypeSpec subscriptFrom = arrayFrom.SubType;
                CLRTypeSpec subscriptTo = arrayTo.SubType;

                if (IsProvablyReferenceType(subscriptFrom))
                    return IsRefAssignable(subscriptFrom, subscriptTo);
                return subscriptFrom.Equals(subscriptTo);
            }
            else if (from is CLRTypeSpecVarOrMVar)
            {
                CLRGenericParamRow genericParam = GenericParamForSpec((CLRTypeSpecVarOrMVar)from);

                if (genericParam.NotNullableValueTypeConstraint)
                    return (to.Equals(m_commonTypes.Object) || to.Equals(m_commonTypes.ValueType));

                if (genericParam.ReferenceTypeConstraint && to.Equals(m_commonTypes.Object))
                    return true;

                foreach (CLRGenericParamConstraintRow constraint in genericParam.Constraints)
                {
                    CLRTypeSpec constraintType = m_builder.Assemblies.InternTypeDefOrRefOrSpec(constraint.Constraint);
                    if (IsRefAssignable(constraintType, to))
                        return true;
                }

                return false;
            }

            throw new ArgumentException();
        }
예제 #30
0
 public BoundInterfaceMethodImpl(CLRTypeSpec definedInType, CppVtableSlot interfaceSlot, CppVtableSlot classSlot)
     : this()
 {
     DefinedInType = definedInType;
     InterfaceSlot = interfaceSlot;
     ClassSlot = classSlot;
 }