public CppAssignabilityResolver(CppBuilder builder, CfgNodeCompiler.CommonTypeLookup commonTypes, CLRTypeDefRow inClass, CLRMethodDefRow inMethod) { m_builder = builder; m_commonTypes = commonTypes; m_inClass = inClass; m_inMethod = inMethod; }
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"); }
public void Parse() { CfgNodeCompiler compiler = new CfgNodeCompiler(this); compiler.Compile(); m_midInstructions = compiler.OutputInstructions; m_fallThroughEdge = compiler.OutputFallThroughEdge; }
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; }
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; }