public InteropIntrinsicAttribute(InteropIntrinsicKind intrinsicKind) { IntrinsicKind = intrinsicKind; }
/// <summary> /// Handles general interop operations. /// </summary> /// <param name="context">The current invocation context.</param> /// <param name="kind">The kind of the interop intrinsic.</param> /// <returns>The resulting value.</returns> protected virtual Value?MakeInterop(InvocationContext context, InteropIntrinsicKind kind) { var compilationContext = context.CompilationContext; var args = context.GetArgs(); var genericArgs = context.GetMethodGenericArguments(); var type = genericArgs.Length > 0 ? genericArgs[0] : null; var llvmType = context.Unit.GetType(type); var builder = context.Builder; var int32Type = context.LLVMContext.Int32Type; switch (kind) { case InteropIntrinsicKind.DestroyStructure: return(new Value(type, BuildStore(builder, args[0].LLVMValue, ConstNull(llvmType)))); case InteropIntrinsicKind.SizeOf: return(new Value(typeof(int), BuildTruncOrBitCast(builder, SizeOf(llvmType), int32Type, string.Empty))); case InteropIntrinsicKind.OffsetOf: { if (type.IsPrimitive) { throw compilationContext.GetNotSupportedException( ErrorMessages.CannotTakeFieldOffsetOfPrimitiveType, type); } // Argument is a GEP var testVal = args[0].LLVMValue; var gepSource = GetOperand(testVal, 0); // First argument is the string const var stringConst = GetOperand(gepSource, 0); var stringPtr = GetAsString(stringConst, out IntPtr size); var sizeVal = size.ToInt32(); if (sizeVal < 2) { throw compilationContext.GetNotSupportedException( ErrorMessages.CannotFindFieldOfType, string.Empty, type); } var fieldName = Marshal.PtrToStringAnsi(stringPtr, Math.Max(sizeVal - 1, 0)); var mappedType = context.Unit.GetObjectType(type); var info = mappedType.ManagedType.GetField(fieldName); if (info == null || !mappedType.TryResolveOffset(info, out int offset)) { throw compilationContext.GetNotSupportedException( ErrorMessages.CannotFindFieldOfType, fieldName, type); } var index = ConstInt(int32Type, offset, false); var offsetPointer = BuildInBoundsGEP( builder, ConstPointerNull(llvmType), out index, 1, string.Empty); var intOffset = BuildPtrToInt(builder, offsetPointer, int32Type, string.Empty); return(new Value(typeof(int), intOffset)); } default: throw compilationContext.GetNotSupportedException( ErrorMessages.NotSupportedIntrinsic, kind); } }