/// <summary>
        /// Returns true if this is a type that doesn't require marshalling.
        /// </summary>
        private static bool IsBlittableType(TypeDesc type)
        {
            type = type.UnderlyingType;

            if (type.IsValueType)
            {
                if (type.IsPrimitive)
                {
                    // All primitive types except char and bool are blittable
                    TypeFlags category = type.Category;
                    if (category == TypeFlags.Boolean || category == TypeFlags.Char)
                        return false;

                    return true;
                }

                foreach (FieldDesc field in type.GetFields())
                {
                    if (field.IsStatic)
                        continue;

                    TypeDesc fieldType = field.FieldType;

                    // TODO: we should also reject fields that specify custom marshalling
                    if (!IsBlittableType(fieldType))
                        return false;
                }
                return true;
            }

            if (type.IsPointer)
                return true;

            return false;
        }
Exemple #2
0
        private int GatherClassGCLayout(TypeDesc type, byte* gcPtrs)
        {
            int result = 0;

            foreach (var field in type.GetFields())
            {
                if (field.IsStatic)
                    continue;

                CorInfoGCType gcType = CorInfoGCType.TYPE_GC_NONE;

                var fieldType = field.FieldType;
                if (fieldType.IsValueType)
                {
                    if (!((MetadataType)fieldType).ContainsPointers)
                        continue;

                    gcType = CorInfoGCType.TYPE_GC_OTHER;
                }
                else if ((fieldType is DefType) || (fieldType is ArrayType))
                {
                    gcType = CorInfoGCType.TYPE_GC_REF;
                }
                else if (fieldType.IsByRef)
                {
                    gcType = CorInfoGCType.TYPE_GC_BYREF;
                }
                else
                {
                    continue;
                }

                Debug.Assert(field.Offset % PointerSize == 0);
                byte* fieldGcPtrs = gcPtrs + field.Offset / PointerSize;

                if (gcType == CorInfoGCType.TYPE_GC_OTHER)
                {
                    result += GatherClassGCLayout(fieldType, fieldGcPtrs);
                }
                else
                {
                    // Ensure that if we have multiple fields with the same offset, 
                    // that we don't double count the data in the gc layout.
                    if (*fieldGcPtrs == (byte)CorInfoGCType.TYPE_GC_NONE)
                    {
                        *fieldGcPtrs = (byte)gcType;
                        result++;
                    }
                    else
                    {
                        Debug.Assert(*fieldGcPtrs == (byte)gcType);
                    }
                }
            }

            return result;
        }
Exemple #3
0
        private void OutputTypeFields(CppGenerationBuffer sb, TypeDesc t)
        {
            bool explicitLayout = false;
            ClassLayoutMetadata classLayoutMetadata = default(ClassLayoutMetadata);

            if (t.IsValueType)
            {
                MetadataType metadataType = (MetadataType)t;
                if (metadataType.IsExplicitLayout)
                {
                    explicitLayout = true;
                    classLayoutMetadata = metadataType.GetClassLayout();
                }
            }

            int instanceFieldIndex = 0;

            if (explicitLayout)
            {
                sb.AppendLine();
                sb.Append("union {");
                sb.Indent();
            }

            foreach (var field in t.GetFields())
            {
                if (field.IsStatic)
                {
                    if (field.IsLiteral)
                        continue;

                    TypeDesc fieldType = GetFieldTypeOrPlaceholder(field);
                    CppGenerationBuffer builder;
                    if (!fieldType.IsValueType)
                    {
                        builder = _gcStatics;
                    }
                    else
                    {
                        // TODO: Valuetype statics with GC references
                        builder = _statics;
                    }
                    builder.AppendLine();
                    builder.Append(GetCppSignatureTypeName(fieldType));
                    builder.Append(" ");
                    builder.Append(GetCppStaticFieldName(field) + ";");
                }
                else
                {
                    if (explicitLayout)
                    {
                        sb.AppendLine();
                        sb.Append("struct {");
                        sb.Indent();
                        int offset = classLayoutMetadata.Offsets[instanceFieldIndex].Offset;
                        if (offset > 0)
                        {
                            sb.AppendLine();
                            sb.Append("char __pad" + instanceFieldIndex + "[" + offset + "];");
                        }
                    }
                    sb.AppendLine();
                    sb.Append(GetCppSignatureTypeName(GetFieldTypeOrPlaceholder(field)) + " " + GetCppFieldName(field) + ";");
                    if (explicitLayout)
                    {
                        sb.Exdent();
                        sb.AppendLine();
                        sb.Append("};");
                    }
                    instanceFieldIndex++;
                }
            }

            if (explicitLayout)
            {
                sb.Exdent();
                sb.AppendLine();
                sb.Append("};");
            }
        }
        private void AddTypeReference(TypeDesc type, bool constructed)
        {
            AddTypeDependency(type, constructed);

            foreach (var field in type.GetFields())
            {
                AddTypeDependency(field.FieldType, false);
            }
        }
Exemple #5
0
        private void OutputType(TypeDesc t, bool full)
        {
            _emittedTypes.Add(t);

            if (full)
            {
                if (!t.IsValueType)
                {
                    var baseType = t.BaseType;
                    if (baseType != null)
                    {
                        if (!_emittedTypes.Contains(baseType))
                        {
                            OutputType(baseType, full);
                        }
                    }
                }

                foreach (var field in t.GetFields())
                {
                    var fieldType = GetFieldTypeOrPlaceholder(field);
                    if (fieldType.IsValueType && !fieldType.IsPrimitive && !field.IsStatic)
                    {
                        if (!_emittedTypes.Contains(fieldType))
                        {
                            OutputType(fieldType, full);
                        }
                    }
                }
            }

            string mangledName = GetCppTypeName(t);

            int nesting = 0;
            int current = 0;
            for (;;)
            {
                int sep = mangledName.IndexOf("::", current);
                if (sep < 0)
                    break;

                Out.Write("namespace " + mangledName.Substring(current, sep - current) + " { ");
                current = sep + 2;

                nesting++;
            }

            if (full)
            {
                Out.Write("class " + mangledName.Substring(current));
                if (!t.IsValueType)
                {
                    var baseType = t.BaseType;
                    if (baseType != null)
                    {
                        Out.Write(" : public " + GetCppTypeName(baseType));
                    }
                }
                Out.WriteLine(" { public:");

                // TODO: Enable once the dependencies are tracked for arrays
                // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked)
                if (!t.IsPointer && !t.IsByRef)
                {
                    Out.WriteLine("static MethodTable * __getMethodTable();");
                }

                List<MethodDesc> virtualSlots;
                _compilation.NodeFactory.VirtualSlots.TryGetValue(t, out virtualSlots);
                if (virtualSlots != null)
                {
                    int baseSlots = 0;
                    var baseType = t.BaseType;
                    while (baseType != null)
                    {
                        List<MethodDesc> baseVirtualSlots;
                        _compilation.NodeFactory.VirtualSlots.TryGetValue(baseType, out baseVirtualSlots);
                        if (baseVirtualSlots != null)
                            baseSlots += baseVirtualSlots.Count;
                        baseType = baseType.BaseType;
                    }

                    for (int slot = 0; slot < virtualSlots.Count; slot++)
                    {
                        MethodDesc virtualMethod = virtualSlots[slot];
                        Out.WriteLine(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot));
                    }
                }
                if (t.IsDelegate)
                {
                    Out.WriteLine(GetCodeForDelegate(t));
                }

                OutputTypeFields(t);

                if (t.HasStaticConstructor)
                {
                    _statics.AppendLine("bool __cctor_" + GetCppTypeName(t).Replace("::", "__") + ";");
                }

                List<MethodDesc> methodList;
                if (_methodLists.TryGetValue(t, out methodList))
                {
                    foreach (var m in methodList)
                    {
                        OutputMethod(m);
                    }
                }
                Out.Write("};");
            }
            else
            {
                Out.Write("class " + mangledName.Substring(current) + ";");
            }

            while (nesting > 0)
            {
                Out.Write(" };");
                nesting--;
            }
            Out.WriteLine();
        }
Exemple #6
0
        private void ExpandType(TypeDesc type)
        {
            if (_emittedTypes.Contains(type))
                return;
            _emittedTypes.Add(type);

            GetCppSignatureTypeName(type);
            var baseType = type.BaseType;
            if (baseType != null)
            {
                ExpandType(baseType);
            }

            foreach (var field in type.GetFields())
            {
                ExpandType(GetFieldTypeOrPlaceholder(field));
            }

            if (type.IsDelegate)
            {
                MethodDesc method = type.GetMethod("Invoke", null);

                var sig = method.Signature;
                ExpandType(sig.ReturnType);
                for (int i = 0; i < sig.Length; i++)
                    ExpandType(sig[i]);
            }

            if (type.IsArray)
            {
                ExpandType(((ArrayType)type).ElementType);
            }
        }
Exemple #7
0
        private void OutputType(CppGenerationBuffer sb, TypeDesc t, bool full)
        {
            _emittedTypes.Add(t);

            if (full)
            {
                if (!t.IsValueType)
                {
                    var baseType = t.BaseType;
                    if (baseType != null)
                    {
                        if (!_emittedTypes.Contains(baseType))
                        {
                            OutputType(sb, baseType, full);
                        }
                    }
                }

                foreach (var field in t.GetFields())
                {
                    var fieldType = GetFieldTypeOrPlaceholder(field);
                    if (fieldType.IsValueType && !fieldType.IsPrimitive && !field.IsStatic)
                    {
                        if (!_emittedTypes.Contains(fieldType))
                        {
                            OutputType(sb, fieldType, full);
                        }
                    }
                }
            }

            string mangledName = GetCppTypeName(t);

            int nesting = 0;
            int current = 0;
            // Create Namespaces. If a mangledName starts with just :: we will simply ignore it.
            sb.AppendLine();
            for (;;)
            {
                int sep = mangledName.IndexOf("::", current);
                if (sep < 0)
                    break;

                if (sep != 0)
                {
                    // Case of a name not starting with ::
                    sb.Append("namespace " + mangledName.Substring(current, sep - current) + " { ");
                    nesting++;
                }
                current = sep + 2;

            }

            if (full)
            {
                sb.Append("class " + mangledName.Substring(current));
                if (!t.IsValueType)
                {
                    if (t.BaseType != null)
                    {
                        sb.Append(" : public " + GetCppTypeName(t.BaseType));
                    }
                }
                sb.Append(" {");
                sb.AppendLine();
                sb.Append("public:");
                sb.Indent();

                // TODO: Enable once the dependencies are tracked for arrays
                // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked)
                if (!t.IsPointer && !t.IsByRef)
                {
                    sb.AppendLine();
                    sb.Append("static MethodTable * __getMethodTable();");
                }

                IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(t).Slots;
                
                int baseSlots = 0;
                var baseType = t.BaseType;
                while (baseType != null)
                {
                    IReadOnlyList<MethodDesc> baseVirtualSlots = _compilation.NodeFactory.VTable(baseType).Slots;
                    if (baseVirtualSlots != null)
                        baseSlots += baseVirtualSlots.Count;
                    baseType = baseType.BaseType;
                }

                for (int slot = 0; slot < virtualSlots.Count; slot++)
                {
                    MethodDesc virtualMethod = virtualSlots[slot];
                    sb.AppendLine();
                    sb.Append(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot));
                }

                if (t.IsDelegate)
                {
                    sb.AppendLine();
                    sb.Append(GetCodeForDelegate(t));
                }

                OutputTypeFields(sb, t);

                if (t.HasStaticConstructor)
                {
                    _statics.AppendLine();
                    _statics.Append("bool __cctor_" + GetCppTypeName(t).Replace("::", "__") + ";");
                }

                List<MethodDesc> methodList;
                if (_methodLists.TryGetValue(t, out methodList))
                {
                    foreach (var m in methodList)
                    {
                        OutputMethod(sb, m);
                    }
                }
                sb.Exdent();
                sb.AppendLine();
                sb.Append("};");
            }
            else
            {
                sb.Append("class " + mangledName.Substring(current) + ";");
            }

            while (nesting > 0)
            {
                sb.Append("};");
                nesting--;
            }

            // Make some rooms between two type definitions
            if (full)
                sb.AppendEmptyLine();
        }
Exemple #8
0
 private void AddInstanceFields(TypeDesc type)
 {
     foreach (var field in type.GetFields())
     {
         if (!field.IsStatic)
         {
             _compilation.AddField(field);
             var fieldType = field.FieldType;
             if (fieldType.IsValueType && !fieldType.IsPrimitive)
                 AddInstanceFields(fieldType);
         }
     }
 }
        /// <summary>
        /// Returns true if struct doesn't have fields that require marshalling.
        /// </summary>
        private static bool IsBlittableStruct(TypeDesc type)
        {
            if (type.IsValueType)
            {
                foreach (FieldDesc field in type.GetFields())
                {
                    if (field.IsStatic)
                        continue;

                    TypeDesc fieldType = field.FieldType;

                    // TODO: we should also reject fields that specify custom marshalling
                    if (!IsSimpleType(fieldType) && !IsBlittableStruct(fieldType))
                        return false;
                }
                return true;
            }

            return false;
        }
Exemple #10
0
        /// <summary>
        /// Returns true if this is a type that doesn't require marshalling.
        /// </summary>
        private static bool IsBlittableType(TypeDesc type)
        {
            type = type.UnderlyingType;

            if (type.IsValueType)
            {
                if (type.IsPrimitive)
                {
                    // All primitive types except char and bool are blittable
                    TypeFlags category = type.Category;
                    if (category == TypeFlags.Boolean || category == TypeFlags.Char)
                        return false;

                    return true;
                }

                foreach (FieldDesc field in type.GetFields())
                {
                    if (field.IsStatic)
                        continue;

                    TypeDesc fieldType = field.FieldType;

                    // TODO: we should also reject fields that specify custom marshalling
                    if (!IsBlittableType(fieldType))
                    {
                        // This field can still be blittable if it's a Char and marshals as Unicode
                        var owningType = field.OwningType as MetadataType;
                        if (owningType == null)
                            return false;

                        if (fieldType.Category != TypeFlags.Char ||
                            owningType.PInvokeStringFormat == PInvokeStringFormat.AnsiClass)
                            return false;
                    }
                }
                return true;
            }

            if (type.IsPointer)
                return true;

            return false;
        }
Exemple #11
0
        private void AddTypeReference(TypeDesc type, bool constructed)
        {
            // CppImporter will rather arbitrarily try to generate types as constructed.
            // Stomp over the choice and only allow this if it remotely makes sense.
            constructed = constructed & ConstructedEETypeNode.CreationAllowed(type);

            AddTypeDependency(type, constructed);

            foreach (var field in type.GetFields())
            {
                AddTypeDependency(field.FieldType, false);
            }
        }