public ValueReference CreateAlloca( TypeNode type, MemoryAddressSpace addressSpace) { return(CreateAlloca( CreatePrimitiveValue(1), type, addressSpace)); }
/// <summary> /// Constructs a new pointer variable. /// </summary> /// <param name="id">The current variable id.</param> /// <param name="elementType">The pointer element type.</param> /// <param name="addressSpace">The associated address space.</param> internal PointerVariable( int id, TypeNode elementType, MemoryAddressSpace addressSpace) : base(id) { AddressSpace = addressSpace; ElementType = elementType; }
private static TypeNode ComputeType( IRContext context, TypeNode allocaType, MemoryAddressSpace addressSpace) { return(context.CreatePointerType( allocaType, addressSpace)); }
/// <summary> /// Creates a local allocation. /// </summary> /// <param name="location">The current location.</param> /// <param name="type">The type of the allocation.</param> /// <param name="addressSpace">The target address space.</param> /// <returns>A node that represents the alloca operation.</returns> public ValueReference CreateAlloca( Location location, TypeNode type, MemoryAddressSpace addressSpace) => CreateAlloca( location, type, addressSpace, CreateUndefined());
/// <summary> /// Returns a cached version of an <see cref="AddressSpaceConverter"/> for known /// address spaces. /// </summary> /// <param name="addressSpace">The address space to convert into.</param> /// <returns>A cached or a new converter instance.</returns> public static AddressSpaceConverter GetAddressSpaceConverter( MemoryAddressSpace addressSpace) { int index = (int)addressSpace; return(index < 0 || index >= TypeConverters.Length ? new AddressSpaceConverter(addressSpace) : TypeConverters[index]); }
/// <summary> /// Creates a view type. /// </summary> /// <param name="elementType">The view element type.</param> /// <param name="addressSpace">The address space.</param> /// <returns>The created view type.</returns> public ViewType CreateViewType( TypeNode elementType, MemoryAddressSpace addressSpace) { Debug.Assert(elementType != null, "Invalid element type"); return(CreateType(new ViewType( elementType, addressSpace))); }
/// <summary> /// Constructs a new view type. /// </summary> /// <param name="typeContext">The parent type context.</param> /// <param name="elementType">The element type.</param> /// <param name="addressSpace">The associated address space.</param> internal ViewType( IRTypeContext typeContext, TypeNode elementType, MemoryAddressSpace addressSpace) : base(typeContext, elementType, addressSpace) { Size = Alignment = 4; AddFlags(TypeFlags.ViewDependent); }
/// <summary> /// Creates a dynamic local memory allocation. /// </summary> /// <param name="location">The current location.</param> /// <param name="type">The type of the allocation.</param> /// <param name="addressSpace">The target address space.</param> /// <returns>A node that represents the alloca operation.</returns> public ValueReference CreateDynamicAllocaArray( Location location, TypeNode type, MemoryAddressSpace addressSpace) => CreateStaticAllocaArray( location, CreateDynamicMemoryLengthValue(location, type, addressSpace), type, addressSpace);
public ValueReference CreateDynamicAllocaArray( Location location, TypeNode type, MemoryAddressSpace addressSpace) => CreateStaticAllocaArray( location, CreatePrimitiveValue(location, -1), type, addressSpace);
/// <summary> /// Returns true if the parent cast is redundant. /// </summary> /// <param name="targetSpace">The target address space.</param> /// <param name="value">The current value to check.</param> /// <returns>True, if the parent cast is redundant.</returns> private static bool IsRedundantRecursive( MemoryAddressSpace targetSpace, Value value) { foreach (var use in value.Uses) { var node = use.Resolve(); switch (node) { case MethodCall call: // We cannot remove casts to other address spaces in case of a // method invocation if the address spaces do not match if (!call.Target.HasImplementation) { break; } var targetParam = call.Target.Parameters[use.Index]; if (targetParam.ParameterType is IAddressSpaceType paramType && paramType.AddressSpace == targetSpace) { return(false); } break; case PhiValue _: // We are not allowed to remove casts in the case of phi values return(false); case Store _: // We are not allowed to remove casts in the case of alloca // stores if (use.Index != 0) { return(false); } break; case SetArrayElement _: case SetField _: // We are not allowed to remove field or array stores to tuples // with different field types return(false); case PointerCast _: case LoadElementAddress _: case LoadFieldAddress _: if (!IsRedundantRecursive(targetSpace, node)) { return(false); } break; } } return(true); }
/// <summary> /// Creates an array based local allocation. /// </summary> /// <param name="location">The current location.</param> /// <param name="arrayLength"> /// The array length (number of elements to allocate). /// </param> /// <param name="type">The type of the allocation.</param> /// <param name="addressSpace">The target address space.</param> /// <returns>A node that represents the alloca operation.</returns> public ValueReference CreateStaticAllocaArray( Location location, Value arrayLength, TypeNode type, MemoryAddressSpace addressSpace) => CreateAlloca( location, type, addressSpace, arrayLength);
/// <summary> /// Constructs a new address type. /// </summary> /// <param name="typeContext">The parent type context.</param> /// <param name="elementType">The element type.</param> /// <param name="addressSpace">The associated address space.</param> protected AddressSpaceType( IRTypeContext typeContext, TypeNode elementType, MemoryAddressSpace addressSpace) : base(typeContext) { Debug.Assert(elementType != null, "Invalid element type"); ElementType = elementType; AddressSpace = addressSpace; AddFlags(elementType.Flags); }
/// <summary cref="IEnumerator.MoveNext"/> public bool MoveNext() { do { Current = (MemoryAddressSpace)(++index); if (Info.HasAddressSpace(Current)) { return(true); } }while (index <= (int)MemoryAddressSpace.Local); return(false); }
/// <summary> /// Constructs a new pointer type. /// </summary> /// <param name="typeContext">The parent type context.</param> /// <param name="elementType">The element type.</param> /// <param name="addressSpace">The associated address space.</param> internal PointerType( IRTypeContext typeContext, TypeNode elementType, MemoryAddressSpace addressSpace) : base(typeContext, elementType, addressSpace) { Size = Alignment = typeContext.Context.TargetPlatform == TargetPlatform.X86 ? 4 : 8; AddFlags(TypeFlags.PointerDependent); }
/// <summary> /// Constructs a new convert value. /// </summary> /// <param name="context">The parent IR context.</param> /// <param name="basicBlock">The parent basic block.</param> /// <param name="value">The value to convert.</param> /// <param name="targetAddressSpace">The target address space.</param> internal AddressSpaceCast( IRContext context, BasicBlock basicBlock, ValueReference value, MemoryAddressSpace targetAddressSpace) : base( basicBlock, value, ComputeType(context, value.Type, targetAddressSpace)) { Debug.Assert( value.Type.IsViewOrPointerType && (value.Type as AddressSpaceType).AddressSpace != targetAddressSpace, "Invalid target address space"); }
/// <summary> /// Creates an address-space cast. /// </summary> /// <param name="location">The current location.</param> /// <param name="node">The operand.</param> /// <param name="targetAddressSpace">The target address space.</param> /// <returns>A node that represents the cast operation.</returns> public ValueReference CreateAddressSpaceCast( Location location, Value node, MemoryAddressSpace targetAddressSpace) { var type = node.Type.As <AddressSpaceType>(location); var sourceAddressSpace = type.AddressSpace; return(sourceAddressSpace == targetAddressSpace ? (ValueReference)node : Append(new AddressSpaceCast( GetInitializer(location), node, targetAddressSpace))); }
public static Type GetManagedType(this MemoryAddressSpace space) { switch (space) { case MemoryAddressSpace.Global: return(typeof(AddressSpaces.Global)); case MemoryAddressSpace.Local: return(typeof(AddressSpaces.Local)); case MemoryAddressSpace.Shared: return(typeof(AddressSpaces.Shared)); default: return(typeof(AddressSpaces.Generic)); } }
/// <summary> /// Creates an address-space cast conversion. /// </summary> /// <param name="sourceRegister">The source register.</param> /// <param name="targetRegister">The target register.</param> /// <param name="sourceAddressSpace">The source address space.</param> /// <param name="targetAddressSpace">The target address space.</param> private void CreateAddressSpaceCast( PrimitiveRegister sourceRegister, HardwareRegister targetRegister, MemoryAddressSpace sourceAddressSpace, MemoryAddressSpace targetAddressSpace) { var toGeneric = targetAddressSpace == MemoryAddressSpace.Generic; var addressSpaceOperation = PTXInstructions.GetAddressSpaceCast(toGeneric); var addressSpaceOperationSuffix = PTXInstructions.GetAddressSpaceCastSuffix(Backend); using var command = BeginCommand(addressSpaceOperation); command.AppendAddressSpace( toGeneric ? sourceAddressSpace : targetAddressSpace); command.AppendSuffix(addressSpaceOperationSuffix); command.AppendArgument(targetRegister); command.AppendArgument(sourceRegister); }
/// <summary> /// Constructs a new pointer type. /// </summary> /// <param name="typeContext">The parent type context.</param> /// <param name="elementType">The element type.</param> /// <param name="addressSpace">The associated address space.</param> internal PointerType( IRTypeContext typeContext, TypeNode elementType, MemoryAddressSpace addressSpace) : base(typeContext, elementType, addressSpace) { if (typeContext.TargetPlatform == TargetPlatform.X86) { Size = Alignment = 4; BasicValueType = BasicValueType.Int32; } else { Size = Alignment = 8; BasicValueType = BasicValueType.Int64; } AddFlags(TypeFlags.PointerDependent); }
/// <summary> /// Tries to specialize a view or a pointer address space. /// </summary> /// <param name="type">The pointer or view type.</param> /// <param name="addressSpace">The target address space.</param> /// <param name="specializedType">The specialized type.</param> /// <returns>True, iff the type could be specialized.</returns> public bool TrySpecializeAddressSpaceType( TypeNode type, MemoryAddressSpace addressSpace, out TypeNode specializedType) { Debug.Assert(type != null, "Invalid type"); if (type is AddressSpaceType addressSpaceType) { specializedType = SpecializeAddressSpaceType( addressSpaceType, addressSpace); } else { specializedType = null; } return(specializedType != null); }
private static AddressSpaceType ComputeType( IRContext context, TypeNode sourceType, MemoryAddressSpace targetAddressSpace) { if (sourceType is ViewType viewType) { return(context.CreateViewType( viewType.ElementType, targetAddressSpace)); } else { var pointerType = sourceType as PointerType; return(context.CreatePointerType( pointerType.ElementType, targetAddressSpace)); } }
/// <summary> /// Appends the given address space /// </summary> /// <param name="addressSpace">The address space.</param> public void AppendAddressSpace(MemoryAddressSpace addressSpace) { switch (addressSpace) { case MemoryAddressSpace.Global: stringBuilder.Append(".global"); break; case MemoryAddressSpace.Shared: stringBuilder.Append(".shared"); break; case MemoryAddressSpace.Local: stringBuilder.Append(".local"); break; default: break; } }
/// <summary> /// Specializes the address space of the given <seeVoidType cref="AddressSpaceType"/>. /// </summary> /// <param name="addressSpaceType">The source type.</param> /// <param name="addressSpace">The new address space.</param> /// <returns>The created specialzized <see cref="AddressSpaceType"/>.</returns> public AddressSpaceType SpecializeAddressSpaceType( AddressSpaceType addressSpaceType, MemoryAddressSpace addressSpace) { Debug.Assert(addressSpaceType != null, "Invalid address space type"); if (addressSpaceType is PointerType pointerType) { return(CreatePointerType( pointerType.ElementType, addressSpace)); } else { var viewType = addressSpaceType as ViewType; return(CreateViewType( viewType.ElementType, addressSpace)); } }
/// <summary> /// Creates a local allocation. /// </summary> /// <param name="location">The current location.</param> /// <param name="type">The type of the allocation.</param> /// <param name="addressSpace">The target address space.</param> /// <param name="arrayLength"> /// The array length (number of elements to allocate or undefined). /// </param> /// <returns>A node that represents the alloca operation.</returns> internal ValueReference CreateAlloca( Location location, TypeNode type, MemoryAddressSpace addressSpace, Value arrayLength) { location.Assert( addressSpace == MemoryAddressSpace.Local || addressSpace == MemoryAddressSpace.Shared); return(arrayLength is PrimitiveValue primitiveValue && primitiveValue.Int32Value == 0 ? CreateNull( location, CreatePointerType(type, addressSpace)) : Append(new Alloca( GetInitializer(location), arrayLength, type, addressSpace))); }
/// <summary> /// Constructs a new alloca node. /// </summary> /// <param name="context">The parent IR context.</param> /// <param name="basicBlock">The parent basic block.</param> /// <param name="arrayLength">The array length to allocate.</param> /// <param name="allocaType">The allocation type.</param> /// <param name="addressSpace">The target address space.</param> internal Alloca( IRContext context, BasicBlock basicBlock, ValueReference arrayLength, TypeNode allocaType, MemoryAddressSpace addressSpace) : base( basicBlock, ImmutableArray.Create(arrayLength), ComputeType(context, allocaType, addressSpace)) { Debug.Assert( addressSpace == MemoryAddressSpace.Local || addressSpace == MemoryAddressSpace.Shared, "Invalid alloca address space"); AllocaType = allocaType; AddressSpace = addressSpace; InvalidateType(); }
/// <summary> /// Creates an address-space cast. /// </summary> /// <param name="location">The current location.</param> /// <param name="node">The operand.</param> /// <param name="targetAddressSpace">The target address space.</param> /// <returns>A node that represents the cast operation.</returns> public ValueReference CreateAddressSpaceCast( Location location, Value node, MemoryAddressSpace targetAddressSpace) { var type = node.Type.As <AddressSpaceType>(location); // Simplify chained casts if (node is AddressSpaceCast cast) { node = cast.Value; type = cast.SourceType; } var sourceAddressSpace = type.AddressSpace; return(sourceAddressSpace == targetAddressSpace ? (ValueReference)node : Append(new AddressSpaceCast( GetInitializer(location), node, targetAddressSpace))); }
/// <summary> /// Creates a new generic view type that relies on an n-dimension index. /// </summary> /// <param name="elementType">The element type.</param> /// <param name="indexType">The index type.</param> /// <param name="addressSpace">The address space.</param> /// <returns>The created view type.</returns> public StructureType CreateGenericViewType( TypeNode elementType, StructureType indexType, MemoryAddressSpace addressSpace) { // Try to resolve the managed type Type managedType = null; if (elementType.TryResolveManagedType(out Type managedElementType) && indexType.TryResolveManagedType(out Type managedIndexType)) { managedType = GenericArrayViewType.MakeGenericType(managedElementType, managedIndexType); } // Create the actual type var viewType = CreateViewType(elementType, addressSpace); return(CreateStructureType( StructureType.Root, ImmutableArray.Create <TypeNode>(viewType, indexType), ImmutableArray <string> .Empty, managedType)); }
/// <summary> /// Creates an address-space cast. /// </summary> /// <param name="node">The operand.</param> /// <param name="targetAddressSpace">The target address space.</param> /// <returns>A node that represents the cast operation.</returns> public ValueReference CreateAddressSpaceCast( Value node, MemoryAddressSpace targetAddressSpace) { Debug.Assert(node != null, "Invalid node"); var type = node.Type as AddressSpaceType; Debug.Assert(type != null, "Invalid address space type"); var sourceAddressSpace = type.AddressSpace; if (sourceAddressSpace == targetAddressSpace) { return(node); } return(Append(new AddressSpaceCast( Context, BasicBlock, node, targetAddressSpace))); }
/// <summary> /// Allocates a pointer type. /// </summary> /// <param name="elementType">The pointer element type to allocate.</param> /// <param name="addressSpace">The associated address space.</param> /// <returns>The allocated variable.</returns> public PointerVariable AllocatePointerType( TypeNode elementType, MemoryAddressSpace addressSpace) => new PointerVariable(idCounter++, elementType, addressSpace);
/// <summary> /// Creates a view type. /// </summary> /// <param name="elementType">The view element type.</param> /// <param name="addressSpace">The address space.</param> /// <returns>The created view type.</returns> public ViewType CreateViewType( TypeNode elementType, MemoryAddressSpace addressSpace) => TypeContext.CreateViewType(elementType, addressSpace);