/// <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); }