/// <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> /// Keeps the IO operation. /// </summary> protected override void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, WriteToOutput writeToOutput) { }
/// <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); }
/// <summary> /// Removes or collects IO operations. /// </summary> private static void Specialize( RewriterContext context, SpecializerData data, WriteToOutput value) { if (data.EnableIOOperations) { data.ToImplement.Add(value); } else { context.Remove(value); } }
/// <summary> /// Constructs a new argument collection. /// </summary> /// <param name="writeToOutput">The parent write node.</param> internal ArgumentCollection(WriteToOutput writeToOutput) { WriteToOutput = writeToOutput; }
/// <summary> /// Constructs a new use enumerator. /// </summary> /// <param name="writeToOutput">The parent write node.</param> internal Enumerator(WriteToOutput writeToOutput) { WriteToOutput = writeToOutput; enumerator = writeToOutput.Expressions.GetEnumerator(); Current = default; }
/// <summary cref="IValueVisitor.Visit(WriteToOutput)"/> public void Visit(WriteToOutput writeToOutput) => throw new InvalidCodeGenerationException();
/// <summary> /// Specializes IO output operations via the instance method /// <see cref="Specialize(in RewriterContext, IRContext, WriteToOutput)"/> of /// the parent <paramref name="data"/> instance. /// </summary> private static void Specialize( RewriterContext context, SpecializerData data, WriteToOutput value) => data.Specializer.Specialize(context, data.Context, value);
/// <summary> /// Specializes IO output operations via the instance method /// <see cref="Specialize(in RewriterContext, WriteToOutput)"/> of the parent /// <paramref name="specializer"/> instance. /// </summary> private static void Specialize( RewriterContext context, AcceleratorSpecializer specializer, WriteToOutput value) => specializer.Specialize(context, value);
/// <summary> /// Specializes IO output operations (if any). Note that this default /// implementation removes the output operations from the current program. /// </summary> /// <param name="context">The parent IR context.</param> /// <param name="methodBuilder">The parent method builder.</param> /// <param name="builder">The current block builder.</param> /// <param name="writeToOutput">The IO output operation.</param> protected virtual void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, WriteToOutput writeToOutput) => builder.Remove(writeToOutput);