コード例 #1
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(TernaryArithmeticValue)"/>
        public void GenerateCode(TernaryArithmeticValue value)
        {
            if (!CLInstructions.TryGetArithmeticOperation(
                    value.Kind,
                    value.BasicValueType.IsFloat(),
                    out string operation))
            {
                throw new InvalidCodeGenerationException();
            }

            var first  = Load(value.First);
            var second = Load(value.Second);
            var third  = Load(value.Third);

            var target = Allocate(value, value.ArithmeticBasicValueType);

            using var statement = BeginStatement(target);
            statement.AppendCast(value.ArithmeticBasicValueType);
            statement.AppendCommand(operation);
            statement.BeginArguments();

            statement.AppendArgument();
            statement.AppendCast(value.ArithmeticBasicValueType);
            statement.Append(first);

            statement.AppendArgument();
            statement.AppendCast(value.ArithmeticBasicValueType);
            statement.Append(second);

            statement.AppendArgument();
            statement.AppendCast(value.ArithmeticBasicValueType);
            statement.Append(third);

            statement.EndArguments();
        }
コード例 #2
0
        /// <summary cref="IValueVisitor.Visit(GenericAtomic)"/>
        public void Visit(GenericAtomic atomic)
        {
            var target = LoadIntrinsic(atomic.Target);
            var value  = LoadIntrinsic(atomic.Value);

            var atomicOperation = CLInstructions.GetAtomicOperation(atomic.Kind);

            StatementEmitter statement;

            if (atomic.Kind == AtomicKind.Exchange)
            {
                var result = AllocateIntrinsic(atomic);
                statement = BeginStatement(result, atomicOperation);
            }
            else
            {
                statement = BeginStatement(atomicOperation);
            }

            statement.BeginArguments();
            statement.AppendAtomicCast(atomic.ArithmeticBasicValueType);
            statement.AppendArgument(target);
            statement.AppendArgument(value);
            statement.EndArguments();

            statement.Dispose();
        }
コード例 #3
0
        public string GetVariableType(Variable variable)
        {
            switch (variable)
            {
            case PrimitiveVariable primitiveVariable:
                return(CLTypeGenerator.GetBasicValueType(primitiveVariable.BasicValueType));

            case PointerVariable pointerType:
            {
                var addressSpacePrefix = CLInstructions.GetAddressSpacePrefix(pointerType.AddressSpace);
                var elementTypeName    = TypeGenerator[pointerType.ElementType];
                if (!string.IsNullOrEmpty(addressSpacePrefix))
                {
                    elementTypeName = addressSpacePrefix + " " + elementTypeName;
                }
                return(elementTypeName + CLInstructions.DereferenceOperation);
            }

            case ObjectVariable objectVariable:
                return(TypeGenerator[objectVariable.Type]);

            default:
                throw new NotSupportedException();
            }
        }
コード例 #4
0
        /// <summary>
        /// Generate all forward type declarations.
        /// </summary>
        /// <param name="builder">The target builder.</param>
        public void GenerateTypeDeclarations(StringBuilder builder)
        {
            foreach (var entry in mapping)
            {
                switch (entry.Key)
                {
                case PointerType pointerType:
                    builder.Append(
                        CLInstructions.TypeDefStatement);
                    builder.Append(' ');
                    builder.Append(
                        CLInstructions.GetAddressSpacePrefix(
                            pointerType.AddressSpace));
                    builder.Append(' ');
                    builder.Append(mapping[pointerType.ElementType]);
                    builder.Append(CLInstructions.DereferenceOperation);
                    builder.Append(' ');
                    builder.Append(entry.Value);
                    builder.AppendLine(";");
                    break;

                case StructureType _:
                    builder.Append(entry.Value);
                    builder.AppendLine(";");
                    break;
                }
            }
            builder.AppendLine();
        }
コード例 #5
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(UnaryArithmeticValue)"/>
        public void GenerateCode(UnaryArithmeticValue value)
        {
            var argument = Load(value.Value);
            var target   = Allocate(
                value,
                value.BasicValueType == BasicValueType.Int1
                ? ArithmeticBasicValueType.UInt1 : value.ArithmeticBasicValueType);

            using var statement = BeginStatement(target);
            if (value.BasicValueType != BasicValueType.Int1)
            {
                statement.AppendCast(value.ArithmeticBasicValueType);
            }
            var operation = CLInstructions.GetArithmeticOperation(
                value.Kind,
                value.ArithmeticBasicValueType,
                out bool isFunction);

            if (isFunction)
            {
                statement.AppendCommand(operation);
            }
            statement.BeginArguments();
            if (!isFunction)
            {
                statement.AppendCommand(operation);
            }

            statement.AppendCast(value.ArithmeticBasicValueType);
            statement.AppendArgument(argument);
            statement.EndArguments();
        }
コード例 #6
0
        /// <summary cref="IValueVisitor.Visit(UnaryArithmeticValue)"/>
        public void Visit(UnaryArithmeticValue value)
        {
            var argument = Load(value.Value);
            var target   = Allocate(value, value.ArithmeticBasicValueType);

            using (var statement = BeginStatement(target))
            {
                statement.AppendCast(value.ArithmeticBasicValueType);
                var operation = CLInstructions.GetArithmeticOperation(
                    value.Kind,
                    value.BasicValueType.IsFloat(),
                    out bool isFunction);

                if (isFunction)
                {
                    statement.AppendCommand(operation);
                }
                statement.BeginArguments();
                if (!isFunction)
                {
                    statement.AppendCommand(operation);
                }

                statement.AppendCast(value.ArithmeticBasicValueType);
                statement.AppendArgument(argument);
                statement.EndArguments();
            }
        }
コード例 #7
0
        /// <summary cref="IValueVisitor.Visit(WarpShuffle)"/>
        public void Visit(WarpShuffle shuffle)
        {
            if (!CLInstructions.TryGetShuffleOperation(
                    Backend.Vendor,
                    shuffle.Kind,
                    out string operation))
            {
                throw new InvalidCodeGenerationException();
            }

            var source = Load(shuffle.Variable);
            var origin = Load(shuffle.Origin);
            var target = Allocate(shuffle);

            using (var statement = BeginStatement(target))
            {
                statement.AppendCommand(operation);
                statement.BeginArguments();

                statement.AppendArgument(source);
                // TODO: create a generic version that does not need this switch
                switch (shuffle.Kind)
                {
                case ShuffleKind.Down:
                case ShuffleKind.Up:
                    statement.AppendArgument(source);
                    break;
                }
                statement.AppendArgument(origin);

                statement.EndArguments();
            }
        }
コード例 #8
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(AddressSpaceCast)"/>
        public void GenerateCode(AddressSpaceCast value)
        {
            var targetType = value.TargetType as AddressSpaceType;
            var source     = Load(value.Value);
            var target     = Allocate(value);

            bool isOperation = CLInstructions.TryGetAddressSpaceCast(
                value.TargetAddressSpace,
                out string operation);

            void GeneratePointerCast(StatementEmitter statement)
            {
                if (isOperation)
                {
                    // There is a specific cast operation
                    statement.AppendCommand(operation);
                    statement.BeginArguments();
                    statement.Append(source);
                }
                else
                {
                    statement.AppendPointerCast(TypeGenerator[targetType.ElementType]);
                }
                statement.Append(source);
            }

            using (var statement = BeginStatement(target))
            {
                GeneratePointerCast(statement);
                if (isOperation)
                {
                    statement.EndArguments();
                }
            }
        }
コード例 #9
0
 /// <summary cref="IBackendCodeGenerator.GenerateCode(Barrier)"/>
 public void GenerateCode(Barrier barrier)
 {
     using var statement = BeginStatement(
               CLInstructions.GetBarrier(barrier.Kind));
     statement.BeginArguments();
     statement.AppendCommand(
         CLInstructions.GetMemoryFenceFlags(true));
     statement.EndArguments();
 }
コード例 #10
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(DynamicMemoryLengthValue)"/>
        public void GenerateCode(DynamicMemoryLengthValue value)
        {
            if (value.AddressSpace != MemoryAddressSpace.Shared)
            {
                throw new InvalidCodeGenerationException();
            }

            // Resolve the name of the global variable containing the length of the
            // shared dynamic memory buffer.
            var dynamicView        = value.GetFirstUseNode().ResolveAs <Alloca>();
            var lengthVariableName = GetSharedMemoryAllocationLengthName(dynamicView);

            // Load the dynamic memory size (in bytes) from the dynamic length variable
            // and divide by the size in bytes of the array element.
            var target = Allocate(value);

            using var statement = BeginStatement(target);
            statement.AppendCast(value.Type);
            var operation = CLInstructions.GetArithmeticOperation(
                BinaryArithmeticKind.Div,
                value.BasicValueType.IsFloat(),
                out bool isFunction);

            if (isFunction)
            {
                statement.AppendCommand(operation);
                statement.BeginArguments();
            }
            else
            {
                statement.OpenParen();
            }

            statement.AppendCast(dynamicView.ArrayLength.Type);
            statement.AppendCommand(lengthVariableName);

            if (!isFunction)
            {
                statement.AppendCommand(operation);
            }

            statement.AppendArgument();
            statement.AppendCast(value.ElementType.BasicValueType);
            statement.AppendConstant(value.ElementType.Size);

            if (isFunction)
            {
                statement.EndArguments();
            }
            else
            {
                statement.CloseParen();
            }
        }
コード例 #11
0
ファイル: CLTypeGenerator.cs プロジェクト: karayakar/ILGPU
 /// <summary cref="ITypeNodeVisitor.Visit(ViewType)"/>
 public void Visit(ViewType type)
 {
     BeginStruct(type);
     Builder.Append('\t');
     Builder.Append(CLInstructions.GetAddressSpacePrefix(type.AddressSpace));
     Builder.Append(' ');
     Builder.Append(TypeGenerator[type.ElementType]);
     Builder.AppendLine("* ptr;");
     Builder.AppendLine("\tint length;");
     EndStruct();
 }
コード例 #12
0
        /// <summary cref="IValueVisitor.Visit(AddressSpaceCast)"/>
        public void Visit(AddressSpaceCast value)
        {
            var targetType = value.TargetType as AddressSpaceType;
            var target     = AllocatePointerType(targetType.ElementType, value.TargetAddressSpace);

            PointerVariable address;

            if (value.IsPointerCast)
            {
                address = LoadAs <PointerVariable>(value.Value);
                Bind(value, target);
            }
            else
            {
                var viewSource = LoadAs <ViewVariable>(value.Value);
                address = viewSource.Pointer;

                var viewTarget = new ViewVariable(
                    value.Type as ViewType,
                    target,
                    viewSource.Length);
                Bind(value, viewTarget);
            }

            if (CLInstructions.TryGetAddressSpaceCast(
                    value.TargetAddressSpace,
                    out string operation))
            {
                // There is a specific cast operation
                using (var statement = BeginStatement(target))
                {
                    statement.AppendCommand(operation);
                    statement.BeginArguments();
                    statement.AppendArgument(address);
                    statement.EndArguments();
                }
            }
            else
            {
                // Use an unspecific generic pointer cast
                using (var statement = BeginStatement(target))
                {
                    statement.AppendCast(
                        TypeGenerator[targetType.ElementType] +
                        CLInstructions.DereferenceOperation);
                    statement.Append(address);
                }
            }
        }
コード例 #13
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(GenericAtomic)"/>
        public void GenerateCode(GenericAtomic atomic)
        {
            var target = Load(atomic.Target);
            var value  = Load(atomic.Value);
            var result = Allocate(atomic);

            var atomicOperation = CLInstructions.GetAtomicOperation(atomic.Kind);

            using var statement = BeginStatement(result, atomicOperation);
            statement.BeginArguments();
            statement.AppendAtomicCast(atomic.ArithmeticBasicValueType);
            statement.AppendArgument(target);
            statement.AppendArgument(value);
            statement.EndArguments();
        }
コード例 #14
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(Broadcast)"/>
        public void GenerateCode(Broadcast broadcast)
        {
            var source = Load(broadcast.Variable);
            var origin = Load(broadcast.Origin);
            var target = Allocate(broadcast);

            using var statement = BeginStatement(target);
            statement.AppendCommand(
                CLInstructions.GetBroadcastOperation(
                    broadcast.Kind));
            statement.BeginArguments();
            statement.AppendArgument(source);
            statement.AppendArgument(origin);
            statement.EndArguments();
        }
コード例 #15
0
ファイル: CLTypeGenerator.cs プロジェクト: karayakar/ILGPU
        /// <summary>
        /// Defines a pointer type in OpenCL (if applicable).
        /// </summary>
        /// <param name="typeNode">The type to define.</param>
        private void DefinePointerType(TypeNode typeNode)
        {
            if (!(typeNode is PointerType pointerType))
            {
                return;
            }

            Builder.Append("typedef ");
            Builder.Append(CLInstructions.GetAddressSpacePrefix(pointerType.AddressSpace));
            Builder.Append(' ');
            Builder.Append(this[pointerType.ElementType]);
            Builder.Append("* ");
            Builder.Append(this[pointerType]);
            Builder.AppendLine(";");
        }
コード例 #16
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(CompareValue)"/>
        public void GenerateCode(CompareValue value)
        {
            var left  = Load(value.Left);
            var right = Load(value.Right);

            var target = Allocate(value);

            using var statement = BeginStatement(target);
            statement.AppendCast(value.CompareType);
            statement.AppendArgument(left);
            statement.AppendCommand(
                CLInstructions.GetCompareOperation(
                    value.Kind));
            statement.AppendCast(value.CompareType);
            statement.AppendArgument(right);
        }
コード例 #17
0
        /// <summary cref="IValueVisitor.Visit(CompareValue)"/>
        public void Visit(CompareValue value)
        {
            var left  = LoadIntrinsic(value.Left);
            var right = LoadIntrinsic(value.Right);

            var targetRegister = AllocateIntrinsic(value);

            using (var statement = BeginStatement(targetRegister))
            {
                statement.AppendArgument(left);
                statement.AppendCommand(
                    CLInstructions.GetCompareOperation(
                        value.Kind));
                statement.AppendArgument(right);
            }
        }
コード例 #18
0
        /// <summary cref="IValueVisitor.Visit(BinaryArithmeticValue)"/>
        public void Visit(BinaryArithmeticValue value)
        {
            var left  = Load(value.Left);
            var right = Load(value.Right);

            var target = Allocate(value, value.ArithmeticBasicValueType);

            using (var statement = BeginStatement(target))
            {
                statement.AppendCast(value.ArithmeticBasicValueType);
                var operation = CLInstructions.GetArithmeticOperation(
                    value.Kind,
                    value.BasicValueType.IsFloat(),
                    out bool isFunction);

                if (isFunction)
                {
                    statement.AppendCommand(operation);
                    statement.BeginArguments();
                }
                else
                {
                    statement.OpenParen();
                }

                statement.AppendCast(value.ArithmeticBasicValueType);
                statement.AppendArgument(left);

                if (!isFunction)
                {
                    statement.AppendCommand(operation);
                }

                statement.AppendArgument();
                statement.AppendCast(value.ArithmeticBasicValueType);
                statement.Append(right);

                if (isFunction)
                {
                    statement.EndArguments();
                }
                else
                {
                    statement.CloseParen();
                }
            }
        }
コード例 #19
0
        /// <summary cref="IValueVisitor.Visit(Broadcast)"/>
        public void Visit(Broadcast broadcast)
        {
            var source = LoadIntrinsic(broadcast.Variable);
            var origin = LoadIntrinsic(broadcast.Origin);
            var target = AllocateIntrinsic(broadcast);

            using (var statement = BeginStatement(target))
            {
                statement.AppendCommand(
                    CLInstructions.GetBroadcastOperation(
                        broadcast.Kind));
                statement.BeginArguments();
                statement.AppendArgument(source);
                statement.AppendArgument(origin);
                statement.EndArguments();
            }
        }
コード例 #20
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(MemoryBarrier)"/>
        public void GenerateCode(MemoryBarrier barrier)
        {
            var fenceFlags = CLInstructions.GetMemoryFenceFlags(true);
            var command    = CLInstructions.GetMemoryBarrier(
                barrier.Kind,
                out string memoryScope);

            using var statement = BeginStatement(command);
            statement.BeginArguments();

            statement.AppendArgument();
            statement.AppendCommand(fenceFlags);

            statement.AppendArgument();
            statement.AppendCommand(memoryScope);

            statement.EndArguments();
        }
コード例 #21
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(PredicateBarrier)"/>
        public void GenerateCode(PredicateBarrier barrier)
        {
            var sourcePredicate = Load(barrier.Predicate);
            var target          = Allocate(barrier);

            if (!CLInstructions.TryGetPredicateBarrier(
                    barrier.Kind,
                    out string operation))
            {
                throw new InvalidCodeGenerationException();
            }

            using var statement = BeginStatement(target);
            statement.AppendCast(BasicValueType.Int1);
            statement.AppendCommand(operation);
            statement.BeginArguments();
            statement.AppendCast(BasicValueType.Int32);
            statement.AppendArgument(sourcePredicate);
            statement.EndArguments();
        }
コード例 #22
0
        /// <summary cref="IValueVisitor.Visit(ViewCast)"/>
        public void Visit(ViewCast value)
        {
            var target = AllocateView(value);
            var source = LoadView(value.Value);

            // Declare view
            Declare(target);

            using (var statement = BeginStatement(target, target.PointerFieldIndex))
            {
                statement.AppendPointerCast(TypeGenerator[target.ElementType]);
                statement.Append(source);
                statement.AppendField(source.PointerFieldIndex);
            }

            var sourceElementSize = ABI.GetSizeOf(value.SourceElementType);
            var targetElementSize = ABI.GetSizeOf(value.TargetElementType);

            // var newLength = length * sourceElementSize / targetElementSize;
            using (var statement = BeginStatement(target, target.LengthFieldIndex))
            {
                statement.OpenParen();
                statement.Append(source);
                statement.AppendField(source.LengthFieldIndex);
                statement.AppendOperation(
                    CLInstructions.GetArithmeticOperation(
                        BinaryArithmeticKind.Mul,
                        false,
                        out bool _));
                statement.AppendConstant(sourceElementSize);
                statement.CloseParen();
                statement.AppendOperation(
                    CLInstructions.GetArithmeticOperation(
                        BinaryArithmeticKind.Div,
                        false,
                        out bool _));
                statement.AppendConstant(targetElementSize);
            }
        }
コード例 #23
0
        /// <summary cref="IValueVisitor.Visit(AtomicCAS)"/>
        public void Visit(AtomicCAS atomicCAS)
        {
            var target  = Load(atomicCAS.Target);
            var value   = Load(atomicCAS.Value);
            var compare = Load(atomicCAS.CompareValue);

            var tempVariable   = AllocateType(BasicValueType.Int1) as PrimitiveVariable;
            var targetVariable = Allocate(atomicCAS);

            using (var statement = BeginStatement(tempVariable))
            {
                statement.AppendCommand(CLInstructions.AtomicCASOperation);
                statement.BeginArguments();
                statement.AppendAtomicCast(atomicCAS.ArithmeticBasicValueType);
                statement.AppendArgument(target);
                statement.AppendArgumentAddressWithCast(value, $"{CLInstructions.GetAddressSpacePrefix(MemoryAddressSpace.Generic)} {CLTypeGenerator.GetBasicValueType(atomicCAS.ArithmeticBasicValueType)} {CLInstructions.DereferenceOperation}");
                statement.AppendArgument(compare);
                statement.EndArguments();
            }

            // The OpenCL way is not compatible with the internal CAS semantic
            // We should adapt to the more general way of returning a bool in the future
            // For now, check the result of the operation and emit an atomic load
            // in the case of a failure.
            using (var statement = BeginStatement(targetVariable))
            {
                statement.Append(tempVariable);
                statement.AppendCommand(CLInstructions.SelectOperation1);
                statement.Append(value);
                statement.AppendCommand(CLInstructions.SelectOperation2);

                statement.AppendCommand(CLInstructions.AtomicLoadOperation);
                statement.BeginArguments();
                statement.AppendAtomicCast(atomicCAS.ArithmeticBasicValueType);
                statement.AppendArgument(target);
                statement.EndArguments();
            }
        }
コード例 #24
0
        /// <summary cref="IValueVisitor.Visit(ViewCast)"/>
        public void Visit(ViewCast value)
        {
            var source  = LoadAs <ViewVariable>(value.Value);
            var pointer = source.Pointer;
            var length  = source.Length;

            var sourceElementSize = ABI.GetSizeOf(value.SourceElementType);
            var targetElementSize = ABI.GetSizeOf(value.TargetElementType);

            // var newLength = length * sourceElementSize / targetElementSize;
            var newLength = AllocateType(BasicValueType.Int32) as PrimitiveVariable;

            using (var statement = BeginStatement(newLength))
            {
                statement.OpenParen();
                statement.Append(length);
                statement.AppendOperation(
                    CLInstructions.GetArithmeticOperation(
                        BinaryArithmeticKind.Mul,
                        false,
                        out bool _));
                statement.AppendConstant(sourceElementSize);
                statement.CloseParen();
                statement.AppendOperation(
                    CLInstructions.GetArithmeticOperation(
                        BinaryArithmeticKind.Div,
                        false,
                        out bool _));
                statement.AppendConstant(targetElementSize);
            }

            var newView = new ViewVariable(
                value.Type as ViewType,
                pointer,
                newLength);

            Bind(value, newView);
        }
コード例 #25
0
        /// <summary cref="IValueVisitor.Visit(AddressSpaceCast)"/>
        public void Visit(AddressSpaceCast value)
        {
            var targetType = value.TargetType as AddressSpaceType;
            var source     = Load(value.Value);
            var target     = Allocate(value);

            bool isOperation = CLInstructions.TryGetAddressSpaceCast(
                value.TargetAddressSpace,
                out string operation);

            void GeneratePointerCast(StatementEmitter statement)
            {
                if (isOperation)
                {
                    // There is a specific cast operation
                    statement.AppendCommand(operation);
                    statement.BeginArguments();
                    statement.Append(source);
                }
                else
                {
                    statement.AppendPointerCast(TypeGenerator[targetType.ElementType]);
                }
                statement.Append(source);
            }

            if (value.IsPointerCast)
            {
                using (var statement = BeginStatement(target))
                {
                    GeneratePointerCast(statement);
                    if (isOperation)
                    {
                        statement.EndArguments();
                    }
                }
            }
            else
            {
                var targetView = target as ViewImplementationVariable;
                Declare(target);

                // Assign pointer
                using (var statement = BeginStatement(target, targetView.PointerFieldIndex))
                {
                    GeneratePointerCast(statement);
                    statement.AppendField(targetView.PointerFieldIndex);
                    if (isOperation)
                    {
                        statement.EndArguments();
                    }
                }

                // Assign length
                using (var statement = BeginStatement(target, targetView.LengthFieldIndex))
                {
                    statement.Append(source);
                    statement.AppendField(targetView.LengthFieldIndex);
                }
            }
        }
コード例 #26
0
 /// <summary cref="IValueVisitor.Visit(Barrier)"/>
 public void Visit(Barrier barrier)
 {
     using (var statement = BeginStatement(
                CLInstructions.GetBarrier(barrier.Kind))) { }
 }
コード例 #27
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(AlignTo)"/>
        public void GenerateCode(AlignTo value)
        {
            // Load the base view pointer
            var source                   = Load(value.Source);
            var target                   = Allocate(value);
            var alignmentVariable        = Load(value.AlignmentInBytes);
            var arithmeticBasicValueType =
                value.Source.BasicValueType.GetArithmeticBasicValueType(true);

            // var baseOffset = (int)ptr & (alignmentInBytes - 1);
            var baseOffset = AllocateType(arithmeticBasicValueType);

            using (var statement = BeginStatement(baseOffset))
            {
                statement.AppendCast(arithmeticBasicValueType);
                statement.AppendArgument(source);
                statement.AppendCommand(CLInstructions.GetArithmeticOperation(
                                            BinaryArithmeticKind.And,
                                            isFloat: false,
                                            out bool _));
                // Optimize for the case in which the alignment is a constant value
                if (value.TryGetAlignmentConstant(out int alignment))
                {
                    statement.AppendConstant(alignment - 1);
                }
                else
                {
                    statement.AppendCommand('(');
                    statement.AppendArgument(alignmentVariable);
                    statement.AppendCommand(CLInstructions.GetArithmeticOperation(
                                                BinaryArithmeticKind.Sub,
                                                isFloat: false,
                                                out bool _));
                    statement.AppendConstant(1);
                    statement.AppendCommand(')');
                }
            }

            // if (baseOffset == 0) { 0 } else { alignment - baseOffset }
            var adjustment = AllocateType(arithmeticBasicValueType);

            using (var selectStatement = BeginStatement(adjustment))
            {
                selectStatement.AppendArgument(baseOffset);
                selectStatement.AppendCommand(" == 0 ? 0 : (");
                if (value.TryGetAlignmentConstant(out int alignmentConstant))
                {
                    selectStatement.AppendConstant(alignmentConstant);
                }
                else
                {
                    selectStatement.AppendArgument(alignmentVariable);
                }
                selectStatement.AppendCommand(CLInstructions.GetArithmeticOperation(
                                                  BinaryArithmeticKind.Sub,
                                                  isFloat: false,
                                                  out bool _));
                selectStatement.AppendArgument(baseOffset);
                selectStatement.AppendCommand(')');
            }

            // Adjust the given pointer
            using var command = BeginStatement(target);
            command.AppendCast(value.Type);
            command.AppendCommand('(');
            command.AppendCast(arithmeticBasicValueType);
            command.AppendArgument(source);
            command.AppendCommand(CLInstructions.GetArithmeticOperation(
                                      BinaryArithmeticKind.Add,
                                      isFloat: false,
                                      out bool _));
            command.AppendArgument(adjustment);
            command.AppendCommand(')');
        }