public SSARewriterContext <TVariable> CreateContext( BasicBlock.Builder builder, HashSet <Value> converted, SSABuilder <TVariable> data) => new SSARewriterContext <TVariable>( new RewriterContext(builder, converted), data);
/// <summary> /// Specializes as-aligned operations (if any) for debugging purposes (if /// enabled). Note that this default implementation does not perform any /// operation. /// </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="asAligned">The current alignment operation.</param> protected virtual void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, AsAligned asAligned) { }
/// <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 debug assertion operation. /// </summary> protected override void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, DebugAssertOperation debugAssert) { }
/// <summary> /// Keeps the IO operation. /// </summary> protected override void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, WriteToOutput writeToOutput) { }
/// <summary> /// Constructs a new basic block. /// </summary> /// <param name="codeGenerator">The parent code generator.</param> /// <param name="builder">The current basic block builder.</param> private Block(CodeGenerator codeGenerator, BasicBlock.Builder builder) { Debug.Assert(codeGenerator != null, "Invalid code generator"); Debug.Assert(builder != null, "Invalid builder"); CodeGenerator = codeGenerator; Builder = builder; }
/// <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> /// Lowers a warp shuffle value by constructing a new one. /// </summary> public ValueReference Lower( BasicBlock.Builder builder, WarpShuffle source, Value newVariable) => builder.CreateShuffle( source.Location, newVariable, source.Origin, source.Kind);
/// <summary> /// Constructs a new value processor. /// </summary> /// <param name="builder">The current builder.</param> /// <param name="converted">The set of converted value.</param> internal RewriterContext( BasicBlock.Builder builder, HashSet <Value> converted) { Debug.Assert(builder != null, "Invalid builder"); Builder = builder; Converted = converted; }
/// <summary> /// Lowers a broadcast value by constructing a new one. /// </summary> public ValueReference Lower( BasicBlock.Builder builder, Broadcast source, Value newVariable) => builder.CreateBroadcast( source.Location, newVariable, source.Origin, source.Kind);
/// <summary> /// Maps internal debug assertions to <see cref="AssertFailed(string, string, /// int, string, int)"/> method calls. /// </summary> protected override void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, DebugAssertOperation debugAssert) { var location = debugAssert.Location; // Create a call to the debug-implementation wrapper while taking the // current source location into account var nextBlock = builder.SplitBlock(debugAssert); var innerBlock = methodBuilder.CreateBasicBlock( location, nameof(AssertFailed)); builder.CreateIfBranch( location, debugAssert.Condition, nextBlock, innerBlock); // Create a call to the assert implementation var innerBuilder = methodBuilder[innerBlock]; var assertFailed = innerBuilder.CreateCall( location, context.Declare(AssertFailedMethod, out var _)); // Move the debug assertion to this block var sourceMessage = debugAssert.Message.ResolveAs <StringValue>(); var message = innerBuilder.CreatePrimitiveValue( location, sourceMessage.String, sourceMessage.Encoding); assertFailed.Add(message); // Append source location information var debugLocation = debugAssert.GetLocationInfo(); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, debugLocation.FileName)); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, debugLocation.Line)); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, debugLocation.Method)); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, 1)); // Finish the actual assertion call and branch assertFailed.Seal(); innerBuilder.CreateBranch(location, nextBlock); // Remove the debug assertion value debugAssert.Replace(builder.CreateUndefined()); }
/// <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); } }
public bool Apply( BasicBlock.Builder blockBuilder, HashSet <Value> converted, Value value) { if (!Rewriter.CanRewrite(Data, value)) { return(false); } TContextProvider provider = default; var rewriterContext = provider.CreateContext( blockBuilder, converted, ContextData); Rewriter.Apply(rewriterContext, Data, value); return(true); }
/// <summary> /// Creates a new <see cref="RewriterContext"/>. /// </summary> public RewriterContext CreateContext( BasicBlock.Builder builder, HashSet <Value> converted, T _) => new RewriterContext(builder, converted);
/// <summary> /// Creates a light-weight rewriter context from the given builder. /// </summary> /// <param name="builder">The parent builder.</param> /// <returns>The created rewriter context.</returns> /// <remarks> /// Note that this context does not support any of the conversion utilities. /// </remarks> public static RewriterContext FromBuilder(BasicBlock.Builder builder) => new RewriterContext(builder, null);
/// <summary cref="IValueLowering{T}.Create(BasicBlock.Builder, Value, T)"/> public Value Create( BasicBlock.Builder builder, Value value, (Value, BroadcastKind) arguments) =>
/// <summary> /// Constructs a new basic block. /// </summary> /// <param name="codeGenerator">The parent code generator.</param> /// <param name="builder">The current basic block builder.</param> private Block(CodeGenerator codeGenerator, BasicBlock.Builder builder) { CodeGenerator = codeGenerator; Builder = builder; }
/// <summary> /// Specializes the build by setting a new block builder. /// </summary> /// <param name="newBuilder">The new builder to use.</param> /// <returns>The specialized rewriter context.</returns> public readonly RewriterContext SpecializeBuilder( BasicBlock.Builder newBuilder) => new RewriterContext(newBuilder, Converted);
/// <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);
/// <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 the build by setting a new block builder. /// </summary> /// <param name="newBuilder">The new builder to use.</param> /// <returns>The specialized rewriter context.</returns> public SSARewriterContext <TVariable> SpecializeBuilder( BasicBlock.Builder newBuilder) => new SSARewriterContext <TVariable>( baseContext.SpecializeBuilder(newBuilder), SSABuilder);
/// <summary> /// Specializes an address-space dependent parameter. /// </summary> /// <param name="methodBuilder">The target method builder.</param> /// <param name="builder">The entry block builder.</param> /// <param name="typeConverter">The type converter to use.</param> /// <param name="parameter">The source parameter.</param> /// <returns>True, if the given parameter was specialized.</returns> private static bool SpecializeParameter( Method.Builder methodBuilder, BasicBlock.Builder builder, AddressSpaceConverter typeConverter, Parameter parameter) { var converted = typeConverter.ConvertType( builder, parameter.Type); var location = parameter.Location; var targetParam = methodBuilder.AddParameter(converted, parameter.Name); if (converted == parameter.Type) { parameter.Replace(targetParam); return(false); } Value convertedValue; if (converted is AddressSpaceType) { convertedValue = builder.CreateAddressSpaceCast( location, targetParam, (parameter.Type as IAddressSpaceType).AddressSpace); } else { var structureType = parameter.Type.As <StructureType>(location); var structureBuilder = builder.CreateStructure( location, structureType); var targetType = converted.As <StructureType>(location); foreach (var(fieldType, access) in structureType) { var field = builder.CreateGetField( location, targetParam, access); if (fieldType == targetType[access]) { structureBuilder.Add(field); } else { structureBuilder.Add( builder.CreateAddressSpaceCast( location, field, (fieldType as IAddressSpaceType).AddressSpace)); } } convertedValue = structureBuilder.Seal(); } parameter.Replace(convertedValue); return(true); }