Exemplo n.º 1
0
        /// <summary>
        /// Gets the type instance for the specified symbol.
        /// </summary>
        /// <param name="parentType">The user type from which this symbol comes from (examples: field type, template type...).</param>
        /// <param name="symbol">The original type.</param>
        /// <param name="bitLength">Number of bits used for this symbol.</param>
        internal virtual TypeInstance GetSymbolTypeInstance(UserType parentType, Symbol symbol, int bitLength = 0)
        {
            switch (symbol.Tag)
            {
            case CodeTypeTag.BuiltinType:
                if (bitLength == 1)
                {
                    return(new BasicTypeInstance(CodeNaming, typeof(bool)));
                }
                switch (symbol.BasicType)
                {
                case BasicType.Bit:
                case BasicType.Bool:
                    return(new BasicTypeInstance(CodeNaming, typeof(bool)));

                case BasicType.Char:
                case BasicType.WChar:
                case BasicType.Char16:
                case BasicType.Char32:
                    return(new BasicTypeInstance(CodeNaming, typeof(char)));

                case BasicType.BSTR:
                    return(new BasicTypeInstance(CodeNaming, typeof(string)));

                case BasicType.Void:
                case BasicType.NoType:
                    return(new BasicTypeInstance(CodeNaming, typeof(VoidType)));

                case BasicType.Float:
                    return(new BasicTypeInstance(CodeNaming, symbol.Size <= 4 ? typeof(float) : typeof(double)));

                case BasicType.Int:
                case BasicType.Long:
                    switch (symbol.Size)
                    {
                    case 0:
                        return(new BasicTypeInstance(CodeNaming, typeof(VoidType)));

                    case 1:
                        return(new BasicTypeInstance(CodeNaming, typeof(sbyte)));

                    case 2:
                        return(new BasicTypeInstance(CodeNaming, typeof(short)));

                    case 4:
                        return(new BasicTypeInstance(CodeNaming, typeof(int)));

                    case 8:
                        return(new BasicTypeInstance(CodeNaming, typeof(long)));

                    default:
                        throw new Exception($"Unexpected type length {symbol.Size}");
                    }

                case BasicType.UInt:
                case BasicType.ULong:
                    switch (symbol.Size)
                    {
                    case 0:
                        return(new BasicTypeInstance(CodeNaming, typeof(VoidType)));

                    case 1:
                        return(new BasicTypeInstance(CodeNaming, typeof(byte)));

                    case 2:
                        return(new BasicTypeInstance(CodeNaming, typeof(ushort)));

                    case 4:
                        return(new BasicTypeInstance(CodeNaming, typeof(uint)));

                    case 8:
                        return(new BasicTypeInstance(CodeNaming, typeof(ulong)));

                    default:
                        throw new Exception($"Unexpected type length {symbol.Size}");
                    }

                case BasicType.Hresult:
                    return(new BasicTypeInstance(CodeNaming, typeof(uint)));        // TODO: Create Hresult type

                default:
                    throw new Exception($"Unexpected basic type {symbol.BasicType}");
                }

            case CodeTypeTag.Pointer:
            {
                Symbol   pointerType = symbol.ElementType;
                UserType pointerUserType;

                // When exporting pointer from Global Modules, always export types as code pointer.
                if (parentType is GlobalsUserType && GetUserType(pointerType, out pointerUserType))
                {
                    return(new PointerTypeInstance(UserTypeInstance.Create(pointerUserType, this)));
                }

                TypeInstance innerType = GetSymbolTypeInstance(parentType, pointerType);

                if (innerType is TemplateArgumentTypeInstance)
                {
                    return(new PointerTypeInstance(innerType));
                }
                switch (pointerType.Tag)
                {
                case CodeTypeTag.BuiltinType:
                case CodeTypeTag.Enum:
                {
                    if ((innerType as BasicTypeInstance)?.BasicType == typeof(VoidType))
                    {
                        return(new BasicTypeInstance(CodeNaming, typeof(NakedPointer)));
                    }
                    return(new PointerTypeInstance(innerType));
                }

                case CodeTypeTag.Class:
                case CodeTypeTag.Structure:
                case CodeTypeTag.Union:
                    return(innerType);

                default:
                    return(new PointerTypeInstance(innerType));
                }
            }

            case CodeTypeTag.Enum:
            case CodeTypeTag.Class:
            case CodeTypeTag.Structure:
            case CodeTypeTag.Union:
            case CodeTypeTag.TemplateArgumentConstant:
            {
                // Try to apply transformation on the type
                UserTypeTransformation transformation = FindTransformation(symbol, parentType);

                if (transformation != null)
                {
                    return(new TransformationTypeInstance(CodeNaming, transformation));
                }

                // Try to find user type that represents current type
                UserType userType;

                if (GetUserType(symbol, out userType))
                {
                    TypeInstance         type         = UserTypeInstance.Create(userType, this);
                    TemplateTypeInstance genericsTree = type as TemplateTypeInstance;

                    if (genericsTree != null && !genericsTree.CanInstantiate)
                    {
                        return(new VariableTypeInstance(CodeNaming));
                    }
                    return(type);
                }

                // We were unable to find user type. If it is enum, use its basic type
                if (symbol.Tag == CodeTypeTag.Enum)
                {
                    return(new BasicTypeInstance(CodeNaming, EnumUserType.GetEnumBasicType(symbol)));
                }

                // Is it template argument constant?
                if (symbol.Tag == CodeTypeTag.TemplateArgumentConstant && symbol.UserType is TemplateArgumentConstantUserType constantArgument)
                {
                    return(new TemplateArgumentConstantTypeInstance(constantArgument));
                }

                // Fall-back to Variable
                return(new VariableTypeInstance(CodeNaming));
            }

            case CodeTypeTag.Array:
                return(new ArrayTypeInstance(GetSymbolTypeInstance(parentType, symbol.ElementType)));

            case CodeTypeTag.Function:
                return(new FunctionTypeInstance(CodeNaming));

            case CodeTypeTag.BaseClass:
            {
                symbol = symbol.Module.GetSymbol(symbol.Name);
                return(GetSymbolTypeInstance(parentType, symbol, bitLength));
            }

            default:
                throw new Exception("Unexpected type tag " + symbol.Tag);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Function that should evaluate <see cref="BaseClass"/> and <see cref="BaseClassOffset"/> properties.
        /// </summary>
        protected virtual Tuple <TypeInstance, int> GetBaseClass(Symbol symbol)
        {
            Symbol[]     baseClasses     = symbol.BaseClasses;
            TypeInstance baseClass       = null;
            int          baseClassOffset = 0;

            // Check if we are exporting only static fields
            if (ExportOnlyStaticFields)
            {
                baseClass = new StaticClassTypeInstance(CodeNaming);
                return(Tuple.Create(baseClass, baseClassOffset));
            }

            // Check if it is inheriting one of its own template arguments
            foreach (Symbol baseClassSymbol in baseClasses)
            {
                TypeInstance typeInstance = Factory.GetSymbolTypeInstance(this, baseClassSymbol);

                if (typeInstance is TemplateArgumentTypeInstance)
                {
                    baseClass = new MultiClassInheritanceTypeInstance(CodeNaming);
                    return(Tuple.Create(baseClass, baseClassOffset));
                }
            }

            // Check if it is recursively inheriting itself
            foreach (Symbol baseClassSymbol in baseClasses)
            {
                UserType userType;

                if (Factory.GetUserType(baseClassSymbol, out userType))
                {
                    if (userType != this && userType is SpecializedTemplateUserType specialization)
                    {
                        userType = specialization.TemplateType;
                    }
                    if (userType == this || (this is SpecializedTemplateUserType specThis && specThis.TemplateType == userType))
                    {
                        baseClass = new MultiClassInheritanceTypeInstance(CodeNaming);
                        return(Tuple.Create(baseClass, baseClassOffset));
                    }
                }
            }

            // Check if it is multi class inheritance
            if (baseClasses.Length > 1)
            {
                int emptyTypes = baseClasses.Count(t => t.IsEmpty);

                if (emptyTypes == baseClasses.Length - 1)
                {
                    UserType userType;
                    Symbol   baseClassSymbol = baseClasses.First(t => !t.IsEmpty);

                    if (!baseClassSymbol.IsVirtualInheritance && Factory.GetUserType(baseClassSymbol, out userType) && !(Factory.GetSymbolTypeInstance(this, baseClassSymbol) is TemplateArgumentTypeInstance))
                    {
                        baseClassOffset = baseClassSymbol.Offset;
                        baseClass       = new SingleClassInheritanceWithInterfacesTypeInstance(userType, Factory);
                        return(Tuple.Create(baseClass, baseClassOffset));
                    }
                }

                baseClass = new MultiClassInheritanceTypeInstance(CodeNaming);
                return(Tuple.Create(baseClass, baseClassOffset));
            }

            // Single class inheritance
            if (baseClasses.Length == 1)
            {
                // Check if base class type is virtual inheritance
                Symbol baseClassType = baseClasses[0];

                if (baseClassType.IsVirtualInheritance)
                {
                    baseClass = new MultiClassInheritanceTypeInstance(CodeNaming);
                    return(Tuple.Create(baseClass, baseClassOffset));
                }

                // Check if base class type should be transformed
                UserTypeTransformation transformation = Factory.FindTransformation(baseClassType, this);

                if (transformation != null)
                {
                    baseClass = new TransformationTypeInstance(CodeNaming, transformation);
                    return(Tuple.Create(baseClass, baseClassOffset));
                }

                // Try to find base class user type
                UserType baseUserType;

                if (Factory.GetUserType(baseClassType, out baseUserType))
                {
                    baseClass = UserTypeInstance.Create(baseUserType, Factory);
                    TemplateTypeInstance genericsInstance = baseClass as TemplateTypeInstance;

                    if (genericsInstance != null && !genericsInstance.CanInstantiate)
                    {
                        // We cannot instantiate the base class, so we must use UserType as the base class.
                        baseClass = new VariableTypeInstance(CodeNaming, false);
                        return(Tuple.Create(baseClass, baseClassOffset));
                    }

                    baseClassOffset = baseClassType.Offset;
                    return(Tuple.Create(baseClass, baseClassOffset));
                }

                // We weren't able to find base class user type. Continue the search.
                return(GetBaseClass(baseClassType));
            }

            // Class doesn't inherit any type
            baseClass = new VariableTypeInstance(CodeNaming, false);
            return(Tuple.Create(baseClass, baseClassOffset));
        }