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)); } }
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; } } }
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); }
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)); } }
public uint ABIAlignmentOfType(Type ty) => LLVM.ABIAlignmentOfType(this.Unwrap(), ty.Unwrap());
public static uint AlignmentOfType(this LLVMTargetDataRef self, LLVMTypeRef type) { return(LLVM.ABIAlignmentOfType(self, type)); }