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(); }
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(); }
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); }
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; }
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; }
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()); }
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(); }
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(); }
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; }
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); }
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"); } } }
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); }
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(); }
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(); }
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); }
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; }
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(); }
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"); }
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(); }
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(); }
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; }
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; }
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); } }
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(); }
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; }
// 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); }
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(); }
public CppClass Instantiate(CLRTypeSpec[] typeParams, CLRTypeSpec[] methodParams) { return new CppClass(this, typeParams, methodParams); }
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(); }
public BoundInterfaceMethodImpl(CLRTypeSpec definedInType, CppVtableSlot interfaceSlot, CppVtableSlot classSlot) : this() { DefinedInType = definedInType; InterfaceSlot = interfaceSlot; ClassSlot = classSlot; }