示例#1
0
        /// <summary>
        /// Maps internal <see cref="WriteToOutput"/> values to
        /// <see cref="PrintF(string)"/> method calls.
        /// </summary>
        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            WriteToOutput writeToOutput)
        {
            var location = writeToOutput.Location;

            // Convert to format string constant
            var expressionString = writeToOutput.ToEscapedPrintFExpression();
            var expression       = builder.CreatePrimitiveValue(
                location,
                expressionString);

            // Create a call to the native printf
            var printFMethod = context.Declare(PrintFMethod, out bool _);
            var callBuilder  = builder.CreateCall(location, printFMethod);

            callBuilder.Add(expression);
            foreach (Value argument in writeToOutput.Arguments)
            {
                var converted = WriteToOutput.ConvertToPrintFArgument(
                    builder,
                    location,
                    argument);
                callBuilder.Add(converted);
            }

            // Replace the write node with the call
            callBuilder.Seal();
            builder.Remove(writeToOutput);
        }
        /// <summary>
        /// Maps internal <see cref="AsAligned"/> values to a debug assertion while
        /// preserving the <see cref="AsAligned"/> value.
        /// </summary>
        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            AsAligned asAligned)
        {
            // Preserve the asAligned operation
            if (!EnableAssertions)
            {
                return;
            }

            // Check the actual pointer alignment
            var location   = asAligned.Location;
            var comparison = builder.CreateCompare(
                location,
                builder.CreateArithmetic(
                    location,
                    builder.CreatePointerAsIntCast(
                        location,
                        asAligned.Source,
                        IntPointerType.BasicValueType),
                    builder.CreateConvert(
                        location,
                        asAligned.AlignmentInBytes,
                        IntPointerType.BasicValueType),
                    BinaryArithmeticKind.Rem),
                builder.CreatePrimitiveValue(
                    location,
                    IntPointerType.BasicValueType,
                    0L),
                CompareKind.Equal);

            // Create the debug assertion
            Value assert = builder.CreateDebugAssert(
                location,
                comparison,
                builder.CreatePrimitiveValue(
                    location,
                    RuntimeErrorMessages.InvalidlyAssumedPointerOrViewAlignment));

            if (assert is DebugAssertOperation assertOperation)
            {
                Implement(context, methodBuilder, builder, assertOperation);
            }
        }
        /// <summary>
        /// Maps internal <see cref="WriteToOutput"/> values to
        /// <see cref="PrintF(string, void*)"/> method calls.
        /// </summary>
        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            WriteToOutput writeToOutput)
        {
            var location = writeToOutput.Location;

            // Convert to format string constant
            var expressionString = writeToOutput.ToPrintFExpression();
            var expression       = builder.CreatePrimitiveValue(
                location,
                expressionString,
                Encoding.ASCII);

            // Create an argument structure that can be passed via local memory
            var argumentBuilder = builder.CreateDynamicStructure(
                location,
                writeToOutput.Count);

            foreach (Value argument in writeToOutput.Arguments)
            {
                var converted = WriteToOutput.ConvertToPrintFArgument(
                    builder,
                    location,
                    argument);
                argumentBuilder.Add(converted);
            }
            var argumentStructure = argumentBuilder.Seal();

            // Create local alloca to store all data
            var alloca = builder.CreateAlloca(
                location,
                argumentStructure.Type,
                MemoryAddressSpace.Local);

            // Store structure into chunk of local memory
            builder.CreateStore(location, alloca, argumentStructure);

            // Cast alloca to the generic address space to satisfy the requirements of
            // of the printf method
            alloca = builder.CreateAddressSpaceCast(
                location,
                alloca,
                MemoryAddressSpace.Generic);

            // Create a call to the native printf
            var printFMethod = context.Declare(PrintFMethod, out bool _);
            var callBuilder  = builder.CreateCall(location, printFMethod);

            callBuilder.Add(expression);
            callBuilder.Add(alloca);

            // Replace the write node with the call
            callBuilder.Seal();
            builder.Remove(writeToOutput);
        }