/// <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="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> /// 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);
/// <summary> /// Specializes debug 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="debugAssert">The debug assert operation.</param> protected virtual void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, DebugAssertOperation debugAssert) => builder.Remove(debugAssert);