/// <summary> /// Lowers set field operations into separate SSA values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> _, AddressSpaceCast value) { var builder = context.Builder; var location = value.Location; var pointer = builder.CreateGetField( location, value.Value, new FieldSpan(0)); var length = builder.CreateGetField( location, value.Value, new FieldSpan(1)); var newPointer = builder.CreateAddressSpaceCast( location, pointer, value.TargetAddressSpace); var newInstance = builder.CreateDynamicStructure( location, newPointer, length); context.ReplaceAndRemove(value, newInstance); }
/// <summary> /// Lowers set field operations into separate SSA values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> _, SubViewValue value) { var builder = context.Builder; var location = value.Location; var pointer = builder.CreateGetField( location, value.Source, new FieldSpan(0)); var newPointer = builder.CreateLoadElementAddress( location, pointer, value.Offset); var length = value.Length; if (length.BasicValueType != BasicValueType.Int64) { length = builder.CreateConvertToInt64( value.Location, length); } var subView = builder.CreateDynamicStructure( location, newPointer, length); context.ReplaceAndRemove(value, subView); }
/// <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 null values with nested types. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, NullValue value) { var targetType = typeConverter.ConvertType(value); var newValue = context.Builder.CreateNull( value.Location, targetType); context.ReplaceAndRemove(value, newValue); }
/// <summary> /// Lowers LFA operations into an adapted version. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, LoadFieldAddress lfa) { // Compute the new span var span = typeConverter.ComputeSpan(lfa, lfa.FieldSpan); var newValue = context.Builder.CreateLoadFieldAddress( lfa.Location, lfa.Source, span); context.ReplaceAndRemove(lfa, newValue); }
/// <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 set field operations into separate SSA values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> typeLowering, ViewCast value) { var builder = context.Builder; var location = value.Location; var pointer = builder.CreateGetField( location, value.Value, new FieldSpan(0)); var length = builder.CreateGetField( location, value.Value, new FieldSpan(1)); // New pointer var newPointer = builder.CreatePointerCast( location, pointer, value.TargetElementType); // Compute new length: // newLength = length * sourceElementSize / targetElementSize; var sourceElementType = (typeLowering[value] as ViewType).ElementType; var sourceElementSize = builder.CreateLongSizeOf( location, sourceElementType); var targetElementSize = builder.CreateLongSizeOf( location, value.TargetElementType); var newLength = builder.CreateArithmetic( location, builder.CreateArithmetic( location, length, sourceElementSize, BinaryArithmeticKind.Mul), targetElementSize, BinaryArithmeticKind.Div); var newInstance = builder.CreateDynamicStructure( location, newPointer, newLength); context.ReplaceAndRemove(value, newInstance); }
/// <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 set field operations into separate SSA values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> _, LoadElementAddress value) { var builder = context.Builder; var location = value.Location; var pointer = builder.CreateGetField( location, value.Source, new FieldSpan(0)); var newLea = builder.CreateLoadElementAddress( location, pointer, value.Offset); context.ReplaceAndRemove(value, newLea); }
/// <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> /// Lowers set field operations into separate SSA values. /// </summary> private static void Lower( RewriterContext context, TypeLowering <ViewType> _, GetViewLength value) { var builder = context.Builder; var length = builder.CreateGetField( value.Location, value.View, new FieldSpan(1)); // Convert to a 32bit length value if (value.Is32BitProperty) { length = builder.CreateConvertToInt32( value.Location, length); } context.ReplaceAndRemove(value, length); }
/// <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> /// Lowers set field operations into separate SSA values. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, GetField getValue) { var builder = context.Builder; var location = getValue.Location; // Compute the new base index var span = typeConverter.ComputeSpan(getValue, getValue.FieldSpan); // Check whether we have to extract a nested type implementation Value newValue; if (typeConverter[getValue] is TType) { // We have to extract multiple elements from this structure var instance = builder.CreateDynamicStructure(location, span.Span); for (int i = 0; i < span.Span; ++i) { var viewField = builder.CreateGetField( location, getValue.ObjectValue, new FieldSpan(span.Index + i)); instance.Add(viewField); } newValue = instance.Seal(); } else { // Simple field access newValue = builder.CreateGetField( location, getValue.ObjectValue, span); } context.ReplaceAndRemove(getValue, newValue); }
/// <summary> /// Lowers structure values with nested types. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, StructureValue value) { var builder = context.Builder; var location = value.Location; var sourceType = typeConverter[value] as StructureType; var instance = builder.CreateStructure( location, typeConverter.ConvertType(sourceType) as StructureType); for (int i = 0, e = sourceType.NumFields; i < e; ++i) { if (sourceType[i] is TType ttype) { var numFields = typeConverter.GetNumFields(ttype); for (int j = 0; j < numFields; ++j) { var viewField = builder.CreateGetField( location, value[i], new FieldSpan(j)); instance.Add(viewField); } } else { instance.Add(value[i]); } } var newValue = instance.Seal(); context.ReplaceAndRemove(value, newValue); }
/// <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> /// Registers a type-mapping entry and returns always true. /// </summary> protected static bool Register <TValue>( TypeLowering <TType> typeConverter, TValue value, TypeNode type) where TValue : Value => typeConverter.Register(value, type);
/// <summary> /// Lowers Phi nodes into an adapted version. /// </summary> protected static void Lower( RewriterContext context, TypeLowering <TType> typeConverter, PhiValue phi) => context.Builder.UpdatePhiType(phi, typeConverter);
/// <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 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()); }
/// <summary> /// Invalidates the type of the given value. /// </summary> protected static void InvalidateType <TValue>( RewriterContext context, TypeLowering <TType> typeConverter, TValue value) where TValue : Value => value.InvalidateType();
/// <summary> /// Registers a type-mapping entry and returns always true. /// </summary> protected static bool Register <TValue>( TypeLowering <TType> typeConverter, TValue value) where TValue : Value => Register(typeConverter, value, value.Type);
/// <summary> /// Returns true if the type is type dependent and registers a type-mapping /// entry. /// </summary> private static bool IsTypeDependent <TValue>( TypeLowering <TType> typeConverter, TValue value) where TValue : Value => IsTypeDependent(typeConverter, value, value.Type);
/// <summary> /// Returns true if the type is type dependent and registers a type-mapping /// entry. /// </summary> private static bool IsTypeDependent <TValue>( TypeLowering <TType> typeConverter, TValue value, TypeNode type) where TValue : Value => typeConverter.TryRegister(value, type);