public CppAssignabilityResolver(CppBuilder builder, CfgNodeCompiler.CommonTypeLookup commonTypes, CLRTypeDefRow inClass, CLRMethodDefRow inMethod)
 {
     m_builder = builder;
     m_commonTypes = commonTypes;
     m_inClass = inClass;
     m_inMethod = inMethod;
 }
Exemple #2
0
        private VType ConvergeVTypes(CfgNodeCompiler nodeCompiler, VType vType1, VType vType2)
        {
            VType.ValTypeEnum convergedValType = VType.ValTypeEnum.Invalid;

            if (vType1.Equals(vType2))
                return vType1;

            if (vType1.ValType == VType.ValTypeEnum.Null)
            {
                if (vType2.ValType == VType.ValTypeEnum.ReferenceValue || vType2.ValType == VType.ValTypeEnum.ConstantReference)
                    return new VType(VType.ValTypeEnum.ReferenceValue, vType1.TypeSpec);
                else
                    throw new ArgumentException();  // Both null should be equal
            }

            if (vType2.ValType == VType.ValTypeEnum.Null)
            {
                if (vType1.ValType == VType.ValTypeEnum.ReferenceValue || vType1.ValType == VType.ValTypeEnum.ConstantReference)
                    return new VType(VType.ValTypeEnum.ReferenceValue, vType2.TypeSpec);
                else
                    throw new ArgumentException();  // Both null should be equal
            }

            if (vType1.ValType == vType2.ValType)
            {
                convergedValType = vType1.ValType;

                if (convergedValType == VType.ValTypeEnum.ConstantValue)
                    convergedValType = VType.ValTypeEnum.ValueValue;
                else if (convergedValType == VType.ValTypeEnum.ConstantReference)
                    convergedValType = VType.ValTypeEnum.ReferenceValue;
            }
            else
            {
                // Different val types
                bool anyMatched = false;
                bool typeMustMatch = false;
                foreach (ValTypeConvergence convergence in ms_convergences)
                    anyMatched = anyMatched || convergence.TryConverge(vType1.ValType, vType2.ValType, ref convergedValType, ref typeMustMatch);

                if (!anyMatched)
                    throw new ArgumentException();

                if (typeMustMatch && !vType1.TypeSpec.Equals(vType2.TypeSpec))
                    throw new ParseFailedException("CFG edge merge failed to merge managed ptrs");
            }

            // Same value type?
            if (vType1.TypeSpec.Equals(vType2.TypeSpec))
                return new VType(convergedValType, vType1.TypeSpec);

            // Different value types
            if (convergedValType == VType.ValTypeEnum.ValueValue)
            {
                // Both are value types, so these must converge
                return new VType(convergedValType, nodeCompiler.ArithConvergeValues(vType1.TypeSpec, vType2.TypeSpec));
            }

            if (convergedValType == VType.ValTypeEnum.ReferenceValue)
            {
                // Both are reference types
                // The merge rules are (where vType1 is the existing type):
                // - If vType2 is assignable to vType1, use vType1
                // - If vType1 is assignable to vType2, use vType2
                // - Otherwise, use closest common supertype
                CppAssignabilityResolver resolver = new CppAssignabilityResolver(nodeCompiler.CppBuilder, nodeCompiler.CommonTypeLookupInst, m_builder.InClass, m_builder.InMethod);
                if (resolver.IsRefAssignable(vType2.TypeSpec, vType1.TypeSpec))
                    return new VType(convergedValType, vType1.TypeSpec);
                if (resolver.IsRefAssignable(vType1.TypeSpec, vType2.TypeSpec))
                    return new VType(convergedValType, vType2.TypeSpec);

                CLRTypeSpec commonBase = resolver.FindCommonBase(vType1.TypeSpec, vType2.TypeSpec);
                if (commonBase == null)
                    throw new ParseFailedException("CFG edge merge failed");

                return new VType(convergedValType, commonBase);
            }

            throw new ParseFailedException("CFG edge merge failed");
        }
Exemple #3
0
        public void Parse()
        {
            CfgNodeCompiler compiler = new CfgNodeCompiler(this);
            compiler.Compile();

            m_midInstructions = compiler.OutputInstructions;
            m_fallThroughEdge = compiler.OutputFallThroughEdge;
        }
Exemple #4
0
        public void UpdateEntryEdge(CfgNodeCompiler nodeCompiler, VType[] newEntryTypes, out bool outNeedsReparse)
        {
            bool needReparse = false;

            int numVTypes = newEntryTypes.Length;
            if (numVTypes != m_entryTypes.Length)
                throw new ArgumentException("Mismatched CFG edge");

            bool anyDifferent = false;
            for (int i = 0; i < numVTypes; i++)
            {
                if (!newEntryTypes[i].Equals(m_entryTypes[i]))
                {
                    anyDifferent = true;
                    break;
                }
            }

            if (anyDifferent)
            {
                needReparse = true;

                VType[] newTypes = new VType[m_entryTypes.Length];
                for (int i = 0; i < numVTypes; i++)
                    newTypes[i] = ConvergeVTypes(nodeCompiler, m_entryTypes[i], newEntryTypes[i]);
                m_entryTypes = newTypes;
            }

            outNeedsReparse = needReparse;
        }
Exemple #5
0
        public CfgNode AddCfgTarget(CfgNodeCompiler nodeCompiler, int startInstr, VType[] entryTypes)
        {
            CfgNode node;
            bool needsReparse = false;
            if (m_cfgNodes.TryGetValue(startInstr, out node))
                node.UpdateEntryEdge(nodeCompiler, entryTypes, out needsReparse);
            else
            {
                node = new CfgNode(this, startInstr, entryTypes);
                needsReparse = true;
                m_cfgNodes.Add(startInstr, node);
            }

            if (needsReparse)
            {
                if (!m_pendingNodesSet.Contains(startInstr))
                {
                    m_pendingNodesSet.Add(startInstr);
                    m_pendingNodesQueue.Enqueue(startInstr);
                }
            }

            return node;
        }