Exemplo n.º 1
0
        private ValueRef CreateDebugType(FunctionCompilerContext functionContext, Type type)
        {
            var size  = LLVM.ABISizeOfType(targetData, type.DefaultType) * 8;
            var align = LLVM.ABIAlignmentOfType(targetData, type.DefaultType) * 8;

            switch (type.TypeReference.MetadataType)
            {
            case MetadataType.Boolean:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "bool", size, align, (uint)DW_ATE.Boolean));

            case MetadataType.SByte:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "sbyte", size, align, (uint)DW_ATE.Signed));

            case MetadataType.Byte:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "byte", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Int16:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "short", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UInt16:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "ushort", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Int32:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "int", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UInt32:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "uint", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Int64:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "long", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UInt64:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "ulong", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Single:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "float", size, align, (uint)DW_ATE.Float));

            case MetadataType.Double:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "double", size, align, (uint)DW_ATE.Float));

            case MetadataType.Char:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "char", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.IntPtr:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "IntPtr", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UIntPtr:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "UIntPtr", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Pointer:
                var elementType = GetType(((PointerType)type.TypeReference).ElementType);
                return(LLVM.DIBuilderCreatePointerType(debugBuilder, CreateDebugType(functionContext, elementType), size, align, type.TypeReference.Name));

            default:
                // For now, let's have a fallback since lot of types are not supported yet.
                return(CreateDebugType(functionContext, intPtr));
            }
        }
Exemplo n.º 2
0
        public DefaultABI(ContextRef context, TargetDataRef targetData)
        {
            this.context    = context;
            this.targetData = targetData;

            var intPtrLLVM = LLVM.PointerType(LLVM.Int8TypeInContext(context), 0);

            intPtrSize = (int)LLVM.ABISizeOfType(targetData, intPtrLLVM);
        }
Exemplo n.º 3
0
        private void ProcessMissingDebugTypes()
        {
            // Process missing debug types.
            // Deferred here to avoid circular issues (when processing fields).
            while (debugClassesToProcess.Count > 0)
            {
                var debugClassToProcess = debugClassesToProcess.Dequeue();
                var @class     = debugClassToProcess.Key;
                var debugClass = debugClassToProcess.Value;
                var type       = @class.Type;

                // Complete members
                if (type.Fields == null)
                {
                    continue;
                }

                var memberTypes = new List <ValueRef>(type.Fields.Count);

                foreach (var field in type.Fields)
                {
                    var fieldType   = CreateDebugType(field.Value.Type);
                    var fieldSize   = LLVM.ABISizeOfType(targetData, field.Value.Type.DefaultTypeLLVM) * 8;
                    var fieldAlign  = LLVM.ABIAlignmentOfType(targetData, field.Value.Type.DefaultTypeLLVM) * 8;
                    var fieldOffset = IsCustomLayout(type.TypeDefinitionCecil) ? (ulong)field.Value.StructIndex * 8 : LLVM.OffsetOfElement(targetData, type.ValueTypeLLVM, (uint)field.Value.StructIndex) * 8;

                    // Add object header (VTable ptr, etc...)
                    if (type.StackType == StackValueType.Object)
                    {
                        fieldOffset += LLVM.OffsetOfElement(targetData, type.ObjectTypeLLVM, (int)ObjectFields.Data) * 8;
                    }

                    memberTypes.Add(LLVM.DIBuilderCreateMemberType(debugBuilder, debugClass, field.Key.Name, ValueRef.Empty, 0, fieldSize, fieldAlign, fieldOffset, 0, fieldType));
                }

                // Update members (mutation)
                // TODO: LLVM.DICompositeTypeSetTypeArray should take a ref, not out.
                var oldDebugClass = debugClass;
                LLVM.DICompositeTypeSetTypeArray(out debugClass, LLVM.DIBuilderGetOrCreateArray(debugBuilder, memberTypes.ToArray()));

                // debugClass being changed, set it again (old value is not valid anymore)
                debugClasses[@class] = debugClass;

                // Same in debugTypeCache (if value type)
                if (debugTypeCache.ContainsKey(@class.Type) && debugTypeCache[@class.Type] == oldDebugClass)
                {
                    debugTypeCache[@class.Type] = debugClass;
                }
            }
        }
Exemplo n.º 4
0
        int GetSize(TypeReference type)
        {
            TypeRef dataType;

            // Try to avoid recursive GetType if possible
            if (type is PointerType || type is ByReferenceType)
            {
                dataType = intPtrLLVM;
            }
            else
            {
                dataType = GetType(type, TypeState.StackComplete).DefaultTypeLLVM;
            }
            return((int)LLVM.ABISizeOfType(targetData, dataType));
        }
Exemplo n.º 5
0
        private ValueRef GetOrCreateDebugClass(Class @class)
        {
            ValueRef debugClass;

            if (debugClasses.TryGetValue(@class, out debugClass))
            {
                return(debugClass);
            }

            var type = @class.Type;

            // Find namespace scope
            var debugNamespace = GetOrCreateDebugNamespace(type.TypeReferenceCecil.Namespace);

            // Create debug version of the class
            var structType = type.StackType == StackValueType.Object ? type.ObjectTypeLLVM : type.ValueTypeLLVM;
            var size       = LLVM.ABISizeOfType(targetData, structType) * 8;
            var align      = LLVM.ABIAlignmentOfType(targetData, structType) * 8;
            var emptyArray = LLVM.DIBuilderGetOrCreateArray(debugBuilder, new ValueRef[0]);

            bool isLocal = type.IsLocal;

            if (isLocal)
            {
                var parentClass      = @class.BaseType;
                var parentDebugClass = parentClass != null?GetOrCreateDebugClass(parentClass) : ValueRef.Empty;

                debugClass = LLVM.DIBuilderCreateClassType(debugBuilder, debugNamespace, type.TypeReferenceCecil.Name, ValueRef.Empty, 0, size, align, 0, 0, parentDebugClass, emptyArray, ValueRef.Empty, ValueRef.Empty, type.TypeReferenceCecil.FullName);
            }
            else
            {
                debugClass = LLVM.DIBuilderCreateForwardDecl(debugBuilder, (int)DW_TAG.class_type, type.TypeReferenceCecil.Name, debugNamespace, ValueRef.Empty, 0, 0, size, align, type.TypeReferenceCecil.FullName);
            }

            debugClasses.Add(@class, debugClass);

            if (isLocal)
            {
                debugClassesToProcess.Enqueue(new KeyValuePair <Class, ValueRef>(@class, debugClass));
            }

            return(debugClass);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Initializes common types.
        /// </summary>
        /// <param name="targetData">Target data.</param>
        /// <param name="compiler">The compiler.</param>
        public static void Init(TargetDataRef targetData, Compiler compiler)
        {
            Int64   = LLVM.Int64Type();
            Int32   = LLVM.Int32Type();
            Int16   = LLVM.Int16Type();
            Int8    = LLVM.Int8Type();
            Boolean = LLVM.Int1Type();
            String  = LLVM.PointerType(LLVM.Int8Type(), 0);
            Void    = LLVM.VoidType();
            Float   = LLVM.FloatType();
            Double  = LLVM.DoubleType();

            VoidPtr       = LLVM.PointerType(LLVM.VoidType(), 0);
            IntPtrSize    = (uint)LLVM.ABISizeOfType(targetData, VoidPtr);
            NativeIntType = LLVM.IntType(IntPtrSize * 8);

            mCompiler = compiler;
            mLookup   = compiler.Lookup;
        }
Exemplo n.º 7
0
        public ABIParameterInfo GetParameterInfo(Type type)
        {
            if (type.StackType == StackValueType.Value)
            {
                // Types smaller than register size will be coerced to integer register type
                var structSize = LLVM.ABISizeOfType(targetData, type.DefaultTypeLLVM);
                if (structSize <= (ulong)intPtrSize)
                {
                    return(new ABIParameterInfo(ABIParameterInfoKind.Coerced, LLVM.IntTypeInContext(context, (uint)structSize * 8)));
                }

                // Otherwise, fallback to passing by pointer + byval (x86) or direct (x64)
                if (intPtrSize == 8)
                {
                    return(new ABIParameterInfo(ABIParameterInfoKind.Direct));
                }
                return(new ABIParameterInfo(ABIParameterInfoKind.Indirect));
            }

            // Other types are passed by value (pointers, int32, int64, float, etc...)
            return(new ABIParameterInfo(ABIParameterInfoKind.Direct));
        }
Exemplo n.º 8
0
        private ValueRef CreateDebugType(Type type)
        {
            ValueRef result;

            if (debugTypeCache.TryGetValue(type, out result))
            {
                return(result);
            }

            ulong size  = 0;
            ulong align = 0;

            switch (type.TypeReferenceCecil.MetadataType)
            {
            case MetadataType.Boolean:
            case MetadataType.SByte:
            case MetadataType.Byte:
            case MetadataType.Int16:
            case MetadataType.UInt16:
            case MetadataType.Int32:
            case MetadataType.UInt32:
            case MetadataType.Int64:
            case MetadataType.UInt64:
            case MetadataType.Single:
            case MetadataType.Double:
            case MetadataType.Char:
            case MetadataType.IntPtr:
            case MetadataType.UIntPtr:
            case MetadataType.Pointer:
            case MetadataType.ByReference:
                size  = LLVM.ABISizeOfType(targetData, type.DefaultTypeLLVM) * 8;
                align = LLVM.ABIAlignmentOfType(targetData, type.DefaultTypeLLVM) * 8;
                break;

            default:
                break;
            }

            switch (type.TypeReferenceCecil.MetadataType)
            {
            case MetadataType.Boolean:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "bool", size, align, (uint)DW_ATE.Boolean));

            case MetadataType.SByte:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "sbyte", size, align, (uint)DW_ATE.Signed));

            case MetadataType.Byte:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "byte", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Int16:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "short", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UInt16:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "ushort", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Int32:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "int", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UInt32:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "uint", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Int64:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "long", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UInt64:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "ulong", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.Single:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "float", size, align, (uint)DW_ATE.Float));

            case MetadataType.Double:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "double", size, align, (uint)DW_ATE.Float));

            case MetadataType.Char:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "char", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.IntPtr:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "IntPtr", size, align, (uint)DW_ATE.Signed));

            case MetadataType.UIntPtr:
                return(LLVM.DIBuilderCreateBasicType(debugBuilder, "UIntPtr", size, align, (uint)DW_ATE.Unsigned));

            case MetadataType.ByReference:
            {
                var elementType = GetType(((ByReferenceType)type.TypeReferenceCecil).ElementType, TypeState.TypeComplete);
                return(LLVM.DIBuilderCreatePointerType(debugBuilder, CreateDebugType(elementType), size, align, type.TypeReferenceCecil.Name));
            }

            case MetadataType.Pointer:
            {
                var elementType = GetType(((PointerType)type.TypeReferenceCecil).ElementType, TypeState.TypeComplete);
                return(LLVM.DIBuilderCreatePointerType(debugBuilder, CreateDebugType(elementType), size, align, type.TypeReferenceCecil.Name));
            }

            case MetadataType.Array:
            case MetadataType.String:
            case MetadataType.TypedByReference:
            case MetadataType.GenericInstance:
            case MetadataType.ValueType:
            case MetadataType.Class:
            case MetadataType.Object:
            {
                var typeDefinition = GetMethodTypeDefinition(type.TypeReferenceCecil);
                if (typeDefinition.IsEnum)
                {
                    var enumDebugType = CreateDebugType(GetType(typeDefinition.GetEnumUnderlyingType(), TypeState.StackComplete));
                    debugTypeCache.Add(type, enumDebugType);

                    return(enumDebugType);
                }

                var debugClass = GetOrCreateDebugClass(GetClass(type));

                // Try again from cache, it might have been done through recursion already
                if (debugTypeCache.TryGetValue(type, out result))
                {
                    return(result);
                }

                if (!typeDefinition.IsValueType)
                {
                    size  = LLVM.ABISizeOfType(targetData, type.DefaultTypeLLVM) * 8;
                    align = LLVM.ABIAlignmentOfType(targetData, type.DefaultTypeLLVM) * 8;

                    debugClass = LLVM.DIBuilderCreatePointerType(debugBuilder, debugClass, size, align, string.Empty);
                }

                debugTypeCache.Add(type, debugClass);

                return(debugClass);
            }

            default:
                // For now, let's have a fallback since lot of types are not supported yet.
                return(CreateDebugType(intPtr));
            }
        }
Exemplo n.º 9
0
        public void InitializeCommonTypes()
        {
            // Load runtime
            runtimeModule = LoadModule(context, @"SharpLang.Runtime.bc");

            // Load data layout from runtime
            var dataLayout = LLVM.GetDataLayout(runtimeModule);

            targetData = LLVM.CreateTargetData(dataLayout);

            // Initialize LLVM types
            intPtrLLVM    = LLVM.PointerType(LLVM.Int8TypeInContext(context), 0);
            int32LLVM     = LLVM.Int32TypeInContext(context);
            int64LLVM     = LLVM.Int64TypeInContext(context);
            intPtrSize    = (int)LLVM.ABISizeOfType(targetData, intPtrLLVM);
            nativeIntLLVM = LLVM.IntTypeInContext(context, (uint)intPtrSize * 8); // Or int64LLVM?

            // Prepare system types, for easier access
            intPtr  = GetType(corlib.MainModule.GetType(typeof(IntPtr).FullName), TypeState.StackComplete);
            int8    = GetType(corlib.MainModule.GetType(typeof(sbyte).FullName), TypeState.StackComplete);
            int16   = GetType(corlib.MainModule.GetType(typeof(short).FullName), TypeState.StackComplete);
            int32   = GetType(corlib.MainModule.GetType(typeof(int).FullName), TypeState.StackComplete);
            int64   = GetType(corlib.MainModule.GetType(typeof(long).FullName), TypeState.StackComplete);
            uint8   = GetType(corlib.MainModule.GetType(typeof(byte).FullName), TypeState.StackComplete);
            uint16  = GetType(corlib.MainModule.GetType(typeof(ushort).FullName), TypeState.StackComplete);
            uint32  = GetType(corlib.MainModule.GetType(typeof(uint).FullName), TypeState.StackComplete);
            uint64  = GetType(corlib.MainModule.GetType(typeof(ulong).FullName), TypeState.StackComplete);
            @bool   = GetType(corlib.MainModule.GetType(typeof(bool).FullName), TypeState.StackComplete);
            @float  = GetType(corlib.MainModule.GetType(typeof(float).FullName), TypeState.StackComplete);
            @double = GetType(corlib.MainModule.GetType(typeof(double).FullName), TypeState.StackComplete);
            @char   = GetType(corlib.MainModule.GetType(typeof(char).FullName), TypeState.StackComplete);
            @object = GetType(corlib.MainModule.GetType(typeof(object).FullName), TypeState.StackComplete);
            @void   = GetType(corlib.MainModule.GetType(typeof(void).FullName), TypeState.StackComplete);

            // struct IMTEntry { i8* interfaceFunctionPtr, i8* functionPtr }
            imtEntryLLVM = LLVM.StructCreateNamed(context, "IMTEntry");
            LLVM.StructSetBody(imtEntryLLVM, new[] { intPtrLLVM, intPtrLLVM }, false);

            // struct CaughtResultType { i8*, i32 }
            caughtResultLLVM = LLVM.StructCreateNamed(context, "CaughtResultType");
            LLVM.StructSetBody(caughtResultLLVM, new[] { intPtrLLVM, int32LLVM }, false);

            // Prepare types used to emit metadata and reflection
            if (!TestMode)
            {
                sharpLangTypeType   = GetType(corlib.MainModule.GetType("System.SharpLangType"), TypeState.StackComplete);
                sharpLangModuleType = GetType(corlib.MainModule.GetType("System.SharpLangModule"), TypeState.StackComplete);
            }
            else
            {
                sharpLangTypeType   = intPtr;
                sharpLangModuleType = intPtr;
            }

            // struct TypeDef { SharpLangModule*, i32 }
            typeDefLLVM = LLVM.StructCreateNamed(context, "TypeDef");
            LLVM.StructSetBody(typeDefLLVM, new[] { sharpLangModuleType.DefaultTypeLLVM, int32LLVM }, false);

            // Import runtime methods
            allocObjectFunctionLLVM           = ImportRuntimeFunction(module, "allocObject");
            resolveInterfaceCallFunctionLLVM  = ImportRuntimeFunction(module, "resolveInterfaceCall");
            isInstInterfaceFunctionLLVM       = ImportRuntimeFunction(module, "isInstInterface");
            throwExceptionFunctionLLVM        = ImportRuntimeFunction(module, "throwException");
            sharpPersonalityFunctionLLVM      = ImportRuntimeFunction(module, "sharpPersonality");
            pinvokeLoadLibraryFunctionLLVM    = ImportRuntimeFunction(module, "PInvokeOpenLibrary");
            pinvokeGetProcAddressFunctionLLVM = ImportRuntimeFunction(module, "PInvokeGetProcAddress");
        }
Exemplo n.º 10
0
 public ulong ABISizeOfType(Type ty) => LLVM.ABISizeOfType(this.Unwrap(), ty.Unwrap());
Exemplo n.º 11
0
        private void CompleteType(Type type)
        {
            var typeReference = type.TypeReferenceCecil;

            switch (typeReference.MetadataType)
            {
            case MetadataType.Pointer:
            case MetadataType.ByReference:
            case MetadataType.RequiredModifier:
                return;
            }

            var valueType      = type.ValueTypeLLVM;
            var typeDefinition = GetMethodTypeDefinition(typeReference);
            var stackType      = type.StackType;

            // Sometime, GetType might already define DataType (for standard CLR types such as int, enum, string, array, etc...).
            // In that case, do not process fields.
            if (type.Fields == null && (LLVM.GetTypeKind(valueType) == TypeKind.StructTypeKind || LLVM.GetTypeKind(valueType) == TypeKind.ArrayTypeKind))
            {
                var fields = new Dictionary <FieldDefinition, Field>(MemberEqualityComparer.Default);

                // Avoid recursion (need a better way?)
                type.Fields = fields;

                var baseType   = GetBaseTypeDefinition(typeReference);
                var parentType = baseType != null?GetType(ResolveGenericsVisitor.Process(typeReference, baseType), TypeState.TypeComplete) : null;

                // Build actual type data (fields)
                // Add fields and vtable slots from parent class
                var fieldTypes = new List <TypeRef>(typeDefinition.Fields.Count + 1);

                if (parentType != null && stackType == StackValueType.Object)
                {
                    fieldTypes.Add(parentType.DataTypeLLVM);
                }

                // Special cases: Array
                if (typeReference.MetadataType == MetadataType.Array)
                {
                    // String: length (native int) + first element pointer
                    var arrayType   = (ArrayType)typeReference;
                    var elementType = GetType(arrayType.ElementType, TypeState.StackComplete);
                    fieldTypes.Add(intPtrLLVM);
                    fieldTypes.Add(LLVM.PointerType(elementType.DefaultTypeLLVM, 0));
                }
                else
                {
                    bool isCustomLayout = IsCustomLayout(typeDefinition); // Do we use a struct or array?
                    int  classSize      = 0;                              // Used for sequential layout

                    foreach (var field in typeDefinition.Fields)
                    {
                        if (field.IsStatic)
                        {
                            continue;
                        }

                        var fieldType = GetType(ResolveGenericsVisitor.Process(typeReference, field.FieldType), TypeState.StackComplete);

                        // Compute struct index (that we can use to access the field). Either struct index or array offset.
                        int structIndex;
                        if (!isCustomLayout)
                        {
                            // Default case, if no custom layout (index so that we can use it in GEP)
                            structIndex = fieldTypes.Count;
                        }
                        else if (typeDefinition.IsExplicitLayout)
                        {
                            structIndex = field.Offset;
                        }
                        else if (typeDefinition.IsSequentialLayout)
                        {
                            // Align for next field, according to packing size
                            classSize   = (classSize + typeDefinition.PackingSize - 1) & ~(typeDefinition.PackingSize - 1);
                            structIndex = classSize;
                            classSize  += (int)LLVM.ABISizeOfType(targetData, fieldType.DefaultTypeLLVM);
                        }
                        else
                        {
                            throw new InvalidOperationException("Invalid class layouting when computing field offsets.");
                        }

                        fields.Add(field, new Field(field, type, fieldType, structIndex));
                        fieldTypes.Add(fieldType.DefaultTypeLLVM);
                    }
                }

                // Set struct (if not custom layout with array type)
                if (LLVM.GetTypeKind(valueType) == TypeKind.StructTypeKind)
                {
                    LLVM.StructSetBody(valueType, fieldTypes.ToArray(), false);
                }
            }
        }