/// <summary> /// Lowers an as-aligned-view operation. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> typeLowering, AsAligned value) { var builder = context.Builder; var location = value.Location; // Extract basic view information from the converted structure var pointer = builder.CreateGetField( location, value.Source, new FieldSpan(0)); var length = builder.CreateGetField( location, value.Source, new FieldSpan(1)); // Ensure that the underyling pointer is aligned var aligned = builder.CreateAsAligned( location, pointer, value.AlignmentInBytes); // Create a new wrapped instance var newInstance = builder.CreateDynamicStructure( location, aligned, length); context.ReplaceAndRemove(value, newInstance); }
/// <summary> /// Lowers leae nodes to linear <see cref="LoadElementAddress"/> values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ArrayType> typeLowering, LoadArrayElementAddress value) { var builder = context.Builder; var location = value.Location; Value array = value.ArrayValue; // Get and validate the array type var structureType = array.Type.As <StructureType>(location); // Compute linear address based on the .Net array layouts Value elementIndex = builder.CreatePrimitiveValue(location, 0L); // (((0 * Width + x) * Height) + y) * Depth + z... for (int i = 0, e = structureType.NumFields - 1; i < e; ++i) { Value length = builder.CreateGetField( location, array, new FieldAccess(1 + i)); // Create a debug assertion to check for out-of-bounds accesses builder.CreateDebugAssert( location, builder.CreateCompare( location, value.Dimensions[i], length, CompareKind.LessThan), builder.CreatePrimitiveValue( location, $"{i}-th array index out of range")); // Update index computation elementIndex = builder.CreateArithmetic( location, elementIndex, length, BinaryArithmeticKind.Mul); elementIndex = builder.CreateArithmetic( location, elementIndex, value.Dimensions[i], BinaryArithmeticKind.Add); } // Extract the actual view field from the structure and compute the // appropriate target element address. var view = GetViewFromArray(builder, location, array); var lea = builder.CreateLoadElementAddress( location, view, elementIndex); context.ReplaceAndRemove(value, lea); }
/// <summary> /// Lowers set field operations into separate SSA values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> _, GetViewLength value) { var length = context.Builder.CreateGetField( value.Location, value.View, new FieldSpan(1)); context.ReplaceAndRemove(value, length); }
/// <summary> /// Lowers set field operations into separate SSA values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> _, NewView value) { var viewInstance = context.Builder.CreateDynamicStructure( value.Location, value.Pointer, value.Length); context.ReplaceAndRemove(value, viewInstance); }
/// <summary> /// Lowers alloca values into their appropriate counter parts. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, Alloca alloca) { // Compute the alloca type var newType = typeConverter.ConvertType(alloca); var newAlloca = context.Builder.CreateAlloca( alloca.Location, newType, alloca.AddressSpace); context.ReplaceAndRemove(alloca, newAlloca); }
/// <summary> /// Lowers pointer cast values into their appropriate counter parts. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, PointerCast cast) { // Compute the cast type var newType = typeConverter.ConvertType(cast); var newCast = context.Builder.CreatePointerCast( cast.Location, cast.Value, newType); context.ReplaceAndRemove(cast, newCast); }
private static void Lower( RewriterContext context, TypeLowering <ArrayType> typeLowering, GetArrayLength value) { var builder = context.Builder; var location = value.Location; Value length; if (value.IsFullLength) { // Extract the view from the underlying array-implementation structure var view = GetViewFromArray(builder, location, value.ArrayValue); length = builder.CreateGetViewLength(location, view); } else { // Check whether the dimension is a compile-time known constant Value dimension = value.Dimension; if (!(dimension is PrimitiveValue primitiveValue)) { throw location.GetNotSupportedException( ErrorMessages.NotSupportNonConstArrayDimension, dimension.ToString()); } // Check whether the field index is out of range var structType = value.ArrayValue.Type.As <StructureType>(location); int index = primitiveValue.Int32Value; if (index < 0 || index >= structType.NumFields - 1) { throw location.GetNotSupportedException( ErrorMessages.NotSupportNonConstArrayDimension, index.ToString()); } // BaseView + dimension offset length = builder.CreateGetField( location, value.ArrayValue, new FieldAccess(1 + index)); } // Replace the actual length information context.ReplaceAndRemove(value, length); }
/// <summary> /// Lowers new array values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ArrayType> typeLowering, ArrayValue value) { var builder = context.Builder; var location = value.Location; int currentPosition = builder.InsertPosition; // Allocate a memory array in the entry block var methodBuilder = builder.MethodBuilder; var entryBlock = methodBuilder[methodBuilder.EntryBlock]; entryBlock.InsertPosition = 0; var arrayLength = entryBlock.ComputeArrayLength( location, value.Extent); var newArray = entryBlock.CreateStaticAllocaArray( location, arrayLength, value.ArrayType.ElementType, MemoryAddressSpace.Local); // Create resulting structure in current block builder.InsertPosition = currentPosition; var instance = builder.CreateDynamicStructure( location, typeLowering.GetNumFields(value.ArrayType)); // Insert pointer field instance.Add(newArray); // Insert all dimensions for (int i = 0, e = value.ArrayType.Dimensions; i < e; ++i) { instance.Add(builder.CreateGetField( location, value.Extent, new FieldSpan(i))); } var newStructure = instance.Seal(); context.ReplaceAndRemove(value, newStructure); }
/// <summary> /// Lowers address-computation values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ArrayType> _, LoadElementAddress value) { var linearAddress = GetLinearAddress( context, value.Source, value.ElementIndex, out var ptr); var newLea = context.Builder.CreateLoadElementAddress( value.Location, ptr, linearAddress); context.ReplaceAndRemove(value, newLea); }
/// <summary> /// Specializes int to native pointer casts. /// </summary> private static void Specialize( RewriterContext context, SpecializerData data, IntAsPointerCast value) { // Convert from int -> native int type -> pointer var builder = context.Builder; // int -> native int type var convertToNativeInt = builder.CreateConvert( value.Location, value.Value, data.IntPointerType); // native int type -> pointer var convert = builder.CreateIntAsPointerCast( value.Location, convertToNativeInt); context.ReplaceAndRemove(value, convert); }
/// <summary> /// Lower array to view casts to direct references to the underyling view. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ArrayType> typeLowering, ArrayToViewCast value) { var builder = context.Builder; var location = value.Location; // Get the view from the array implementation structure Value array = value.Value; var view = GetViewFromArray(builder, location, array); // Cast this view into the generic address space to match all invariants view = builder.CreateAddressSpaceCast( location, view, MemoryAddressSpace.Generic); // Replace the current cast with the actual view pointing to the elements context.ReplaceAndRemove(value, view); }
/// <summary> /// Lowers set field operations into separate SSA values. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, SetField setValue) { var builder = context.Builder; var location = setValue.Location; // Compute the new base index var span = typeConverter.ComputeSpan(setValue, setValue.FieldSpan); // Check whether we have to insert multiple elements Value targetValue = setValue.ObjectValue; if (typeConverter[setValue] is TType) { for (int i = 0; i < span.Span; ++i) { var viewField = builder.CreateGetField( location, setValue.Value, new FieldSpan(i)); targetValue = builder.CreateSetField( location, targetValue, new FieldSpan(span.Index + i), viewField); } } else { // Simple field access targetValue = builder.CreateSetField( location, targetValue, span, setValue.Value); } context.ReplaceAndRemove(setValue, targetValue); }
/// <summary> /// Lowers get element values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ArrayType> _, GetArrayElement value) { var linearAddress = GetLinearAddress( context, value.ObjectValue, value.Index, out var ptr); var builder = context.Builder; var address = builder.CreateLoadElementAddress( value.Location, ptr, linearAddress); var newLoad = builder.CreateLoad( value.Location, address); context.ReplaceAndRemove(value, newLoad); }
/// <summary> /// Specializes native pointer to int casts. /// </summary> private static void Specialize( RewriterContext context, SpecializerData data, PointerAsIntCast value) { // Convert from ptr -> native int type -> desired int type var builder = context.Builder; // ptr -> native int type var convertToNativeType = builder.CreatePointerAsIntCast( value.Location, value.Value, data.IntPointerType.BasicValueType); // native int type -> desired int type var convert = builder.CreateConvert( value.Location, convertToNativeType, value.TargetType); context.ReplaceAndRemove(value, convert); }
/// <summary> /// Lowers array extent values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ArrayType> typeLowering, GetArrayExtent value) { var builder = context.Builder; // Create new extent structure based on all dimension entries int dimensions = StructureType.GetNumFields(typeLowering[value]); var instance = builder.CreateDynamicStructure(value.Location, dimensions); // Insert all dimension values for (int i = 0; i < dimensions; ++i) { instance.Add(builder.CreateGetField( value.Location, value.ObjectValue, new FieldSpan(i + ArrayTypeLowering.DimensionOffset))); } var newStructure = instance.Seal(); context.ReplaceAndRemove(value, newStructure); }
/// <summary> /// Lowers an align-view-to operation. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> typeLowering, AlignViewTo value) { var builder = context.Builder; var location = value.Location; // Extract basic view information from the converted structure var pointer = builder.CreateGetField( location, value.View, new FieldSpan(0)); var length = builder.CreateGetField( location, value.View, new FieldSpan(1)); // Create IR code that represents the required operations to create aligned // views (see ArrayView.AlignToInternal for more information). var viewType = typeLowering[value].As <ViewType>(value); // long elementsToSkip = Min( // AlignmentOffset(ptr, alignmentInBytes) / elementSize, // Length); var elementsToSkip = builder.CreateArithmetic( location, builder.CreateAlignmentOffset( location, builder.CreatePointerAsIntCast( location, pointer, BasicValueType.Int64), value.AlignmentInBytes), builder.CreateSizeOf(location, viewType.ElementType), BinaryArithmeticKind.Div); elementsToSkip = builder.CreateArithmetic( location, elementsToSkip, length, BinaryArithmeticKind.Min); // Build the final result structure instance var resultBuilder = builder.CreateDynamicStructure(location); // Create the prefix view that starts at the original pointer offset and // includes elementsToSkip many elements. { resultBuilder.Add(pointer); resultBuilder.Add(elementsToSkip); } // Create the main view that starts at the original pointer offset + // elementsToSkip and has a length of remainingLength { var mainPointer = builder.CreateLoadElementAddress( location, pointer, elementsToSkip); resultBuilder.Add(mainPointer); var remainingLength = builder.CreateArithmetic( location, length, elementsToSkip, BinaryArithmeticKind.Sub); resultBuilder.Add(remainingLength); } var result = resultBuilder.Seal(); context.ReplaceAndRemove(value, result); }
/// <summary> /// Lowers an align-view-to operation. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> typeLowering, AlignTo value) { var builder = context.Builder; var location = value.Location; // Extract basic view information from the converted structure var pointer = builder.CreateGetField( location, value.Source, new FieldSpan(0)); var length = builder.CreateGetField( location, value.Source, new FieldSpan(1)); // Build the final result structure instance var resultBuilder = builder.CreateDynamicStructure(location); // Convert the current input pointer to a 64-bit integer value var pointerAsInt = builder.CreatePointerAsIntCast( location, pointer, BasicValueType.Int64); // Compute the aligned pointer and convert it to an integer value var aligned = builder.CreateAlignTo( location, pointer, value.AlignmentInBytes); var alignedAsInt = builder.CreatePointerAsIntCast( location, aligned, BasicValueType.Int64); // Compute the number of elements to skip: // Min((aligned - ptr) / SizeOf(ElementType), length) var viewType = typeLowering[value].As <ViewType>(location); var elementsToSkip = builder.CreateArithmetic( location, builder.CreateArithmetic( location, builder.CreateArithmetic( location, alignedAsInt, pointerAsInt, BinaryArithmeticKind.Sub), builder.CreateSizeOf(location, viewType.ElementType), BinaryArithmeticKind.Div), length, BinaryArithmeticKind.Min); // Create the prefix view that starts at the original pointer offset and // includes elementsToSkip many elements. { resultBuilder.Add(pointer); resultBuilder.Add(elementsToSkip); } // Create the main view that starts at the aligned pointer offset and has a // length of remainingLength { resultBuilder.Add(aligned); var remainingLength = builder.CreateArithmetic( location, length, elementsToSkip, BinaryArithmeticKind.Sub); resultBuilder.Add(remainingLength); } var result = resultBuilder.Seal(); context.ReplaceAndRemove(value, result); }
/// <summary> /// Lowers new array values into static allocation instances and structures. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ArrayType> typeLowering, NewArray value) { var builder = context.Builder; var location = value.Location; var targetAddressSpace = (typeLowering as ArrayTypeLowering) .TargetAddressSpace; // Compute array length Value totalLength = builder.CreatePrimitiveValue(location, 1); foreach (Value length in value) { totalLength = builder.CreateArithmetic( location, totalLength, length, BinaryArithmeticKind.Mul); } // Check for a compile-time known constant if (!(totalLength is PrimitiveValue primitiveLength) || primitiveLength.Int32Value < 0) { throw location.GetNotSupportedException( ErrorMessages.NotSupportNonConstArrayDimension, totalLength.ToString()); } // Create array structure. var arrayType = typeLowering .ConvertType(value.Type) .As <StructureType>(location); var result = builder.CreateStructure(location, arrayType); Value view; // Check for empty array allocations if (primitiveLength.HasIntValue(0)) { // Create an empty view. view = builder.CreateNewView( location, builder.CreateNull( location, builder.CreatePointerType( value.ElementType, targetAddressSpace)), primitiveLength); result.Add(view); // Insert a dimension length of 0 in each dimension for (int i = 0, e = value.Count; i < e; ++i) { result.Add(primitiveLength); } } else { // Create the allocation and the base view var allocation = builder.CreateStaticAllocaArray( location, totalLength, value.ElementType, targetAddressSpace); view = builder.CreateNewView(location, allocation, totalLength); result.Add(view); // Insert dimension information for each array rank foreach (Value length in value) { result.Add(length); } } // Clear all array elements using explicit stores. We emit the code in // the form of an unrolled loop to avoid additional loops from being // generated. // TODO: replace this loop with a high-level memset operation later on var defaultElement = builder.CreateNull(location, value.Type.ElementType); for (int i = 0, e = primitiveLength.Int32Value; i < e; ++i) { var address = builder.CreateLoadElementAddress( location, view, builder.CreatePrimitiveValue(location, i)); builder.CreateStore(location, address, defaultElement); } // Replace the current value with a new structure instance context.ReplaceAndRemove(value, result.Seal()); }