// TechDebt: for some of the types below, it would be nicer to return named types, which we can do now that we're // passing around an LLVM context. public static LLVMTypeRef AsLLVMType(this ContextWrapper context, NIType niType) { switch (niType.GetKind()) { case NITypeKind.UInt8: case NITypeKind.Int8: return(context.Int8Type); case NITypeKind.UInt16: case NITypeKind.Int16: return(context.Int16Type); case NITypeKind.UInt32: case NITypeKind.Int32: return(context.Int32Type); case NITypeKind.UInt64: case NITypeKind.Int64: return(context.Int64Type); case NITypeKind.Boolean: return(context.Int1Type); case NITypeKind.String: return(context.StringType()); default: { if (niType.IsRebarReferenceType()) { NIType referentType = niType.GetReferentType(); if (referentType == DataTypes.StringSliceType) { return(context.StringSliceReferenceType()); } NIType sliceElementType; if (referentType.TryDestructureSliceType(out sliceElementType)) { return(context.CreateLLVMSliceReferenceType(context.AsLLVMType(sliceElementType))); } return(LLVMTypeRef.PointerType(context.AsLLVMType(referentType), 0u)); } if (niType.IsCluster()) { LLVMTypeRef[] fieldTypes = niType.GetFields().Select(field => context.AsLLVMType(field.GetDataType())).ToArray(); return(context.StructType(fieldTypes)); } if (niType == DataTypes.FileHandleType) { return(context.FileHandleType()); } if (niType == DataTypes.FakeDropType) { return(context.FakeDropType()); } if (niType == DataTypes.RangeIteratorType) { return(context.RangeIteratorType()); } if (niType == DataTypes.WakerType) { return(context.WakerType()); } NIType innerType; if (niType.TryDestructureOptionType(out innerType)) { return(context.CreateLLVMOptionType(context.AsLLVMType(innerType))); } if (niType.IsStringSplitIteratorType()) { return(context.StringSplitIteratorType()); } if (niType.TryDestructureVectorType(out innerType)) { return(context.CreateLLVMVectorType(context.AsLLVMType(innerType))); } if (niType.TryDestructureSliceIteratorType(out innerType) || niType.TryDestructureSliceMutableIteratorType(out innerType)) { return(context.CreateLLVMSliceIteratorType(context.AsLLVMType(innerType))); } if (niType.TryDestructureSharedType(out innerType)) { return(context.CreateLLVMSharedType(context.AsLLVMType(innerType))); } if (niType.TryDestructureYieldPromiseType(out innerType)) { return(context.CreateLLVMYieldPromiseType(context.AsLLVMType(innerType))); } if (niType.TryDestructureMethodCallPromiseType(out innerType)) { return(context.CreateLLVMMethodCallPromiseType(context.AsLLVMType(innerType))); } if (niType.TryDestructureNotifierReaderType(out innerType)) { return(context.CreateLLVMNotifierReaderType(context.AsLLVMType(innerType))); } if (niType.TryDestructureNotifierReaderPromiseType(out innerType)) { return(context.CreateLLVMNotifierReaderPromiseType(context.AsLLVMType(innerType))); } if (niType.TryDestructureNotifierWriterType(out innerType)) { return(context.CreateLLVMNotifierWriterType(context.AsLLVMType(innerType))); } if (niType.TryDestructurePanicResultType(out innerType)) { return(context.CreateLLVMPanicResultType(context.AsLLVMType(innerType))); } // TODO: when using typedef classes and unions in FunctionCompiler, the LLVM type should // come from a TypeDiagramBuiltPackage. if (niType.IsValueClass() && niType.GetFields().Any()) { LLVMTypeRef[] fieldTypes = niType.GetFields().Select(f => context.AsLLVMType(f.GetDataType())).ToArray(); return(context.StructType(fieldTypes)); } if (niType.IsUnion()) { int maxSize = 4; foreach (NIType field in niType.GetFields()) { // TODO: where possible, use a non-array type that matches the max size LLVMTypeRef llvmFieldType = context.AsLLVMType(field.GetDataType()); int fieldSize = (int)LLVMSharp.LLVM.StoreSizeOfType(LocalTargetInfo.TargetData, llvmFieldType); maxSize = Math.Max(maxSize, fieldSize); } LLVMTypeRef[] structFieldTypes = new LLVMTypeRef[] { context.Int8Type, // TODO: this is incorrect because it does not consider alignment LLVMTypeRef.ArrayType(context.Int8Type, (uint)maxSize) }; return(context.StructType(structFieldTypes)); } throw new NotSupportedException("Unsupported type: " + niType); } } }