Ejemplo n.º 1
0
        public CSharpTypePrinterResult VisitArrayType(ArrayType array,
                                                      TypeQualifiers quals)
        {
            if (ContextKind == CSharpTypePrinterContextKind.Native &&
                array.SizeType == ArrayType.ArraySize.Constant)
            {
                Type arrayType = array.Type.Desugar();

                PrimitiveType primitiveType;
                if (arrayType.IsPointerToPrimitiveType(out primitiveType) &&
                    !(arrayType is FunctionType))
                {
                    if (primitiveType == PrimitiveType.Void)
                    {
                        return("void**");
                    }
                    return(string.Format("{0}*", array.Type.Visit(this, quals)));
                }

                Class @class;
                if (arrayType.TryGetClass(out @class))
                {
                    return(new CSharpTypePrinterResult()
                    {
                        Type = "fixed byte",
                        NameSuffix = string.Format("[{0}]", array.Size * @class.Layout.Size)
                    });
                }

                var arrayElemType = array.Type.Visit(this, quals).ToString();

                // C# does not support fixed arrays of machine pointer type (void* or IntPtr).
                // In that case, replace it by a pointer to an integer type of the same size.
                if (arrayElemType == IntPtrType)
                {
                    arrayElemType = driver.TargetInfo.PointerWidth == 64 ? "long" : "int";
                }

                // Do not write the fixed keyword multiple times for nested array types
                var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed ";
                return(new CSharpTypePrinterResult()
                {
                    Type = string.Format("{0}{1}", fixedKeyword, arrayElemType),
                    NameSuffix = string.Format("[{0}]", array.Size)
                });
            }

            // const char* and const char[] are the same so we can use a string
            if (array.SizeType == ArrayType.ArraySize.Incomplete &&
                array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) &&
                array.QualifiedType.Qualifiers.IsConst)
            {
                return("string");
            }

            return(string.Format("{0}[]", array.Type.Visit(this)));

            // C# only supports fixed arrays in unsafe sections
            // and they are constrained to a set of built-in types.
        }
Ejemplo n.º 2
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar();

            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
                }
                else
                {
                    if (type.IsPointer())
                    {
                        Context.Return.Write("{0}{1}.{2}",
                                             method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                                ? string.Empty
                                : string.Format("ReferenceEquals({0}, null) ? global::System.IntPtr.Zero : ", param),
                                             param, Helpers.InstanceIdentifier, type);
                    }
                    else
                    {
                        if (method == null ||
                            // redundant for comparison operators, they are handled in a special way
                            (method.OperatorKind != CXXOperatorKind.EqualEqual &&
                             method.OperatorKind != CXXOperatorKind.ExclaimEqual))
                        {
                            Context.SupportBefore.WriteLine("if (ReferenceEquals({0}, null))", param);
                            Context.SupportBefore.WriteLineIndent(
                                "throw new global::System.ArgumentNullException(\"{0}\", " +
                                "\"Cannot be null because it is a C++ reference (&).\");",
                                param);
                        }
                        Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
                    }
                }
                return;
            }

            var realClass           = @class.OriginalClass ?? @class;
            var qualifiedIdentifier = realClass.Visit(this.typePrinter);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}.Internal{3}() : *({1}.Internal{3}*) ({0}.{2})", param,
                qualifiedIdentifier, Helpers.InstanceIdentifier, Helpers.GetSuffixForInternal(@class));
        }
Ejemplo n.º 3
0
        public CSharpTypePrinterResult VisitArrayType(ArrayType array,
                                                      TypeQualifiers quals)
        {
            if (ContextKind == CSharpTypePrinterContextKind.Native &&
                array.SizeType == ArrayType.ArraySize.Constant)
            {
                Type          arrayType = array.Type.Desugar();
                PrimitiveType primitiveType;
                if (arrayType.IsPointerToPrimitiveType(out primitiveType))
                {
                    if (primitiveType == PrimitiveType.Void)
                    {
                        return("void**");
                    }
                    return(string.Format("{0}*", array.Type.Visit(this, quals)));
                }

                Class @class;
                if (arrayType.TryGetClass(out @class))
                {
                    return(new CSharpTypePrinterResult()
                    {
                        Type = "fixed byte",
                        NameSuffix = string.Format("[{0}]", array.Size * @class.Layout.Size)
                    });
                }

                // Do not write the fixed keyword multiple times for nested array types
                var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed ";
                return(new CSharpTypePrinterResult()
                {
                    Type = string.Format("{0}{1}", fixedKeyword, array.Type.Visit(this, quals)),
                    NameSuffix = string.Format("[{0}]", array.Size)
                });
            }

            // const char* and const char[] are the same so we can use a string
            if (array.SizeType == ArrayType.ArraySize.Incomplete &&
                array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) &&
                array.QualifiedType.Qualifiers.IsConst)
            {
                return("string");
            }

            return(string.Format("{0}[]", array.Type.Visit(this)));

            // C# only supports fixed arrays in unsafe sections
            // and they are constrained to a set of built-in types.
        }
Ejemplo n.º 4
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar();

            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
                }
                else
                {
                    Context.Return.Write("{0}{1}.{2}",
                                         method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                            ? string.Empty
                            : string.Format("ReferenceEquals({0}, null) ? global::System.IntPtr.Zero : ", param),
                                         param,
                                         Helpers.InstanceIdentifier, type);
                }
                return;
            }

            var qualifiedIdentifier = CSharpMarshalNativeToManagedPrinter.QualifiedIdentifier(
                @class.OriginalClass ?? @class);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}.Internal() : *({1}.Internal*) ({0}.{2})", param,
                qualifiedIdentifier, Helpers.InstanceIdentifier);
        }
Ejemplo n.º 5
0
        public override TypePrinterResult VisitArrayType(ArrayType array,
                                                         TypeQualifiers quals)
        {
            Type arrayType = array.Type.Desugar();

            if (ContextKind == TypePrinterContextKind.Native &&
                array.SizeType == ArrayType.ArraySize.Constant)
            {
                PrimitiveType primitiveType;
                if ((arrayType.IsPointerToPrimitiveType(out primitiveType) &&
                     !(arrayType is FunctionType)) ||
                    (arrayType.IsPrimitiveType() && MarshalKind != MarshalKind.NativeField))
                {
                    if (primitiveType == PrimitiveType.Void)
                    {
                        return("void*");
                    }
                    return(string.Format("{0}", array.Type.Visit(this, quals)));
                }

                if (Parameter != null)
                {
                    return(string.Format("global::System.IntPtr"));
                }

                Enumeration @enum;
                if (arrayType.TryGetEnum(out @enum))
                {
                    return(new TypePrinterResult
                    {
                        Type = string.Format("fixed {0}", @enum.BuiltinType),
                        NameSuffix = string.Format("[{0}]", array.Size)
                    });
                }

                Class @class;
                if (arrayType.TryGetClass(out @class))
                {
                    return(new TypePrinterResult
                    {
                        Type = "fixed byte",
                        NameSuffix = string.Format("[{0}]", array.Size * @class.Layout.Size)
                    });
                }

                var arrayElemType = array.Type.Visit(this, quals).ToString();

                // C# does not support fixed arrays of machine pointer type (void* or IntPtr).
                // In that case, replace it by a pointer to an integer type of the same size.
                if (arrayElemType == IntPtrType)
                {
                    arrayElemType = Context.TargetInfo.PointerWidth == 64 ? "long" : "int";
                }

                // Do not write the fixed keyword multiple times for nested array types
                var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed ";
                return(new TypePrinterResult
                {
                    Type = string.Format("{0}{1}", fixedKeyword, arrayElemType),
                    NameSuffix = string.Format("[{0}]", array.Size)
                });
            }

            // const char* and const char[] are the same so we can use a string
            if (array.SizeType == ArrayType.ArraySize.Incomplete &&
                arrayType.IsPrimitiveType(PrimitiveType.Char) &&
                array.QualifiedType.Qualifiers.IsConst)
            {
                return("string");
            }

            if (arrayType.IsPointerToPrimitiveType(PrimitiveType.Char))
            {
                return("char**");
            }

            return(string.Format("{0}{1}", array.Type.Visit(this),
                                 array.SizeType == ArrayType.ArraySize.Constant ? "[]" :
                                 (ContextKind == TypePrinterContextKind.Managed ? "*" : string.Empty)));

            // C# only supports fixed arrays in unsafe sections
            // and they are constrained to a set of built-in types.
        }
Ejemplo n.º 6
0
        public override TypePrinterResult VisitArrayType(ArrayType array,
                                                         TypeQualifiers quals)
        {
            Type arrayType = array.Type.Desugar();

            if ((MarshalKind == MarshalKind.NativeField ||
                 (ContextKind == TypePrinterContextKind.Native &&
                  MarshalKind == MarshalKind.ReturnVariableArray)) &&
                array.SizeType == ArrayType.ArraySize.Constant)
            {
                if (array.Size == 0)
                {
                    var pointer = new PointerType(array.QualifiedType);
                    return(pointer.Visit(this));
                }

                PrimitiveType primitiveType;
                if ((arrayType.IsPointerToPrimitiveType(out primitiveType) &&
                     !(arrayType is FunctionType)) ||
                    (arrayType.IsPrimitiveType() && MarshalKind != MarshalKind.NativeField))
                {
                    if (primitiveType == PrimitiveType.Void)
                    {
                        return("void*");
                    }

                    return(array.QualifiedType.Visit(this));
                }

                if (Parameter != null)
                {
                    return(IntPtrType);
                }

                Enumeration @enum;
                if (arrayType.TryGetEnum(out @enum))
                {
                    return(new TypePrinterResult
                    {
                        Type = $"fixed {@enum.BuiltinType}",
                        NameSuffix = $"[{array.Size}]"
                    });
                }

                Class @class;
                if (arrayType.TryGetClass(out @class))
                {
                    return(new TypePrinterResult
                    {
                        Type = "fixed byte",
                        NameSuffix = $"[{array.Size * @class.Layout.Size}]"
                    });
                }

                var arrayElemType = array.QualifiedType.Visit(this).ToString();

                // C# does not support fixed arrays of machine pointer type (void* or IntPtr).
                // In that case, replace it by a pointer to an integer type of the same size.
                if (arrayElemType == IntPtrType)
                {
                    arrayElemType = Context.TargetInfo.PointerWidth == 64 ? "long" : "int";
                }

                // Do not write the fixed keyword multiple times for nested array types
                var fixedKeyword = arrayType is ArrayType ? string.Empty : "fixed ";
                return(new TypePrinterResult
                {
                    Type = $"{fixedKeyword}{arrayElemType}",
                    NameSuffix = $"[{array.Size}]"
                });
            }

            // const char* and const char[] are the same so we can use a string
            if (array.SizeType == ArrayType.ArraySize.Incomplete &&
                arrayType.IsPrimitiveType(PrimitiveType.Char) &&
                array.QualifiedType.Qualifiers.IsConst)
            {
                return("string");
            }

            if (arrayType.IsPointerToPrimitiveType(PrimitiveType.Char))
            {
                var prefix = ContextKind == TypePrinterContextKind.Managed ? string.Empty :
                             "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] ";
                return($"{prefix}string[]");
            }

            var arraySuffix = array.SizeType != ArrayType.ArraySize.Constant &&
                              MarshalKind == MarshalKind.ReturnVariableArray ?
                              (ContextKind == TypePrinterContextKind.Managed &&
                               arrayType.IsPrimitiveType() ? "*" : string.Empty) : "[]";

            return($"{arrayType.Visit(this)}{arraySuffix}");
        }
Ejemplo n.º 7
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar(resolveTemplateSubstitution: false);
            string paramInstance;
            Class  @interface;
            var    finalType    = type.GetFinalPointee() ?? type;
            var    templateType = finalType as TemplateParameterSubstitutionType;

            type = Context.Parameter.Type.Desugar();
            if (finalType.TryGetClass(out @interface) &&
                @interface.IsInterface)
            {
                paramInstance = $"{param}.__PointerTo{@interface.OriginalClass.Name}";
            }
            else
            {
                paramInstance = $@"{
                    (templateType != null ? $"(({@class.Visit(typePrinter)}) (object) " : string.Empty)}{
                    param}{(templateType != null ? ")" : string.Empty)
                    }.{Helpers.InstanceIdentifier}";
            }
            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write(paramInstance);
                }
                else
                {
                    if (type.IsPointer())
                    {
                        Context.Return.Write("{0}{1}",
                                             method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                                ? string.Empty
                                : $"ReferenceEquals({param}, null) ? global::System.IntPtr.Zero : ",
                                             paramInstance);
                    }
                    else
                    {
                        if (method == null ||
                            // redundant for comparison operators, they are handled in a special way
                            (method.OperatorKind != CXXOperatorKind.EqualEqual &&
                             method.OperatorKind != CXXOperatorKind.ExclaimEqual))
                        {
                            Context.Before.WriteLine("if (ReferenceEquals({0}, null))", param);
                            Context.Before.WriteLineIndent(
                                "throw new global::System.ArgumentNullException(\"{0}\", " +
                                "\"Cannot be null because it is a C++ reference (&).\");",
                                param);
                        }
                        Context.Return.Write(paramInstance);
                    }
                }
                return;
            }

            var realClass           = @class.OriginalClass ?? @class;
            var qualifiedIdentifier = typePrinter.PrintNative(realClass);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}() : *({1}*) {2}",
                param, qualifiedIdentifier, paramInstance);
        }