private TypeTree FixTypeTree(TypeTree typeTree, Symbol type, UserTypeFactory factory) { // Check basic type BasicTypeTree basicTypeTree = typeTree as BasicTypeTree; if (basicTypeTree != null) { // Basic type tree is not challenged against template arguments, so try to do that. UserType basicUserType; if (CreateFactory(factory).GetUserType(type, out basicUserType)) { TypeTree tree = UserTypeTree.Create(basicUserType, factory); if (tree != null) { return(tree); } } // Failed to match the type // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now. return(new VariableTypeTree()); } // Check array type ArrayTypeTree arrayTypeTree = typeTree as ArrayTypeTree; if (arrayTypeTree != null) { TypeTree elementTypeTree = FixTypeTree(arrayTypeTree.ElementType, type.ElementType, factory); if (elementTypeTree != arrayTypeTree.ElementType) { return(new ArrayTypeTree(elementTypeTree)); } return(arrayTypeTree); } // Check pointer type PointerTypeTree pointerTypeTree = typeTree as PointerTypeTree; if (pointerTypeTree != null) { TypeTree elementTypeTree = FixTypeTree(pointerTypeTree.ElementType, type.ElementType, factory); if (elementTypeTree != pointerTypeTree.ElementType) { return(new PointerTypeTree(elementTypeTree)); } return(pointerTypeTree); } return(typeTree); }
/// <summary> /// Gets the type tree for the specified field. /// </summary> /// <param name="field">The field.</param> /// <param name="factory">The user type factory.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> /// <param name="bitLength">Number of bits used for this symbol.</param> protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0) { // Do not match specializations when getting type for base class. if (extractingBaseClass || NumberOfTemplateArguments == 0) { return(GetSymbolTypeTree(field.Type, factory, bitLength)); } // Check field in all specializations var specializedFields = SpecializedTypes.Select(r => new Tuple <TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray(); if (specializedFields.Any(r => r.Item2 == null)) { // TODO: Incorrect bucketization. Field does not exist in all specialization. return(GetSymbolTypeTree(field.Type, factory, bitLength)); } if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name)) { // There is no specialization, all types across the specializations are the same. return(GetSymbolTypeTree(field.Type, factory, bitLength)); } // Try to get type tree TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength); if (result is BasicTypeTree) { // Basic type tree is not challenged against template arguments, so try to do that. UserType basicUserType; if (CreateFactory(factory).GetUserType(field.Type, out basicUserType)) { TypeTree tree = UserTypeTree.Create(basicUserType, factory); if (tree != null) { return(tree); } } // Failed to match the type // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now. return(new VariableTypeTree()); } return(result); }
/// <summary> /// Gets the type tree for the base class. /// If class has multi inheritance, it can return MultiClassInheritanceTypeTree or SingleClassInheritanceWithInterfacesTypeTree. /// </summary> /// <param name="error">The error text writer.</param> /// <param name="type">The type for which we are getting base class.</param> /// <param name="factory">The user type factory.</param> /// <param name="baseClassOffset">The base class offset.</param> protected override TypeTree GetBaseClassTypeTree(TextWriter error, Symbol type, UserTypeFactory factory, out int baseClassOffset) { TypeTree baseType = base.GetBaseClassTypeTree(error, type, CreateFactory(factory), out baseClassOffset); // Check if base type is template argument. It if is, export it as if it is multi class inheritance. UserTypeTree userBaseType = baseType as UserTypeTree; TemplateArgumentUserType primitiveUserType = userBaseType != null ? userBaseType.UserType as TemplateArgumentUserType : null; if (userBaseType != null && primitiveUserType != null) { var dict = GetGenericTypeConstraintsDictionary(factory); string commonBaseClass; if (dict.TryGetValue(primitiveUserType.ClassName, out commonBaseClass)) { return(UserTypeTree.Create(new TemplateArgumentUserType(commonBaseClass, null), factory)); } baseClassOffset = 0; return(new MultiClassInheritanceTypeTree()); } return(baseType); }
/// <summary> /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function. /// Do not use this function directly, unless you are calling it from overridden function. /// </summary> /// <param name="field">The symbol field.</param> /// <param name="fieldType">The field tree type.</param> /// <param name="factory">The user type factory.</param> /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param> /// <param name="gettingField">The code for getting field variable.</param> /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param> /// <param name="generationFlags">The user type generation flags.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass) { // Physical code generation make sense only for non-static fields if (!isStatic) { bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields); bool cacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields); bool cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields); string constructorText = ""; string fieldName = field.Name; string fieldTypeString = fieldType.GetTypeString(); BasicTypeTree baseType = fieldType as BasicTypeTree; ArrayTypeTree codeArrayType = fieldType as ArrayTypeTree; UserTypeTree userType = fieldType as UserTypeTree; TransformationTypeTree transformationType = fieldType as TransformationTypeTree; bool isEmbedded = field.Type.Tag != CodeTypeTag.Pointer; // Specialization for basic types if (baseType != null) { if (baseType.BasicType == "string") { int charSize = field.Type.ElementType.Size; constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize); } else if (baseType.BasicType != "NakedPointer") { if (field.LocationType == LocationType.BitField) { constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition); } else { constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset); } } } // Specialization for arrays else if (codeArrayType != null) { if (codeArrayType.ElementType is BasicTypeTree) { baseType = (BasicTypeTree)codeArrayType.ElementType; if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer") { int arraySize = field.Type.Size; int elementSize = field.Type.ElementType.Size; if (baseType.BasicType == "char") { constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize); } else { constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize); } fieldTypeString = baseType.GetTypeString() + "[]"; } } } // Specialization for user types else if (userType != null && !extractingBaseClass) { if (!(userType.UserType is EnumUserType)) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) { thisClassCodeType = ClassCodeType; } else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } // Check if type is embedded if (!isEmbedded) { // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly if (IsTypeUsingStaticCodeType(this)) { constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType); } else { constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size); usedThisClass = true; } // Do downcasting if field has vtable if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0) { constructorText += ".DowncastObject()"; } } else { // If user type is embedded, we can reuse memory buffer that we already have in this class string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName); if (IsTypeUsingStaticCodeType(userType.UserType)) { fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType); } else if (IsTypeUsingStaticCodeType(this)) { fieldCodeType = AddFieldCodeType(fieldName); } constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName); } } else { // TODO: This is enum. Read how much enum base type is big and just cast to enum type... } } // Specialization for transformations else if (transformationType != null) { if (!isEmbedded) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) { thisClassCodeType = ClassCodeType; } else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress); if (transformationType.Transformation.Transformation.HasPhysicalConstructor) { fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset); } simpleFieldValue = fieldVariable; constructorText = string.Format("new {0}({1})", fieldTypeString, fieldVariable); } } // If we found suitable physical representation, generate the field if (!string.IsNullOrEmpty(constructorText)) { return new UserTypeField() { ConstructorText = constructorText, FieldName = "_" + fieldName, FieldType = fieldTypeString, FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName), PropertyName = UserTypeField.GetPropertyName(field, this), Static = isStatic, UseUserMember = lazyCacheUserTypeFields, CacheResult = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields), SimpleFieldValue = simpleFieldValue, } } ; } return(base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass)); }