/// <summary> /// Lowers a thread value. /// </summary> private static void LowerThreadValue <TValue, TLoweringImplementation>( SSARewriterContext <FieldRef> context, StructureType structureType, TValue value) where TValue : ThreadValue where TLoweringImplementation : LowerThreadIntrinsics.ILoweringImplementation <TValue> { // We require a single input var variable = AssembleStructure( context, structureType, value.Variable); // Build a new thread value using the assembled structure TLoweringImplementation implementation = default; var newValue = implementation.Lower( context.Builder, value, variable).ResolveAs <TValue>(); // Disassemble the resulting structure value DisassembleStructure(context, structureType, newValue); // Replace old value with new value context.ReplaceAndRemove(value, newValue); }
/// <summary> /// Lowers method calls involving structure types. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, MethodCall call) { // Check for structure arguments that need to be rebuilt var callBuilder = context.Builder.CreateCall(call.Location, call.Target); foreach (Value argument in call) { Value newArgument = argument; if (argument.Type is StructureType argumentType) { newArgument = AssembleStructure( context, argumentType, argument); } callBuilder.Add(newArgument); } // Create new call node var newCall = callBuilder.Seal(); context.ReplaceAndRemove(call, newCall); // Convert the return value if (call.Type is StructureType callType) { DisassembleStructure( context, callType, newCall); } }
/// <summary> /// Lowers get field operations into separate SSA values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, GetField getField) { if (getField.Type is StructureType structureType) { foreach (var(_, fieldAccess) in structureType) { // Get the source value var value = context.GetValue( context.Block, new FieldRef( getField.ObjectValue, new FieldSpan( getField.FieldSpan.Index + fieldAccess.Index))); // Bind the mapped SSA value context.SetValue( context.Block, new FieldRef(getField, fieldAccess), value); } context.Remove(getField); } else { var getFieldValue = context.GetValue( context.Block, new FieldRef(getField.ObjectValue, getField.FieldSpan)); context.ReplaceAndRemove(getField, getFieldValue); } }
/// <summary> /// Keeps structure store operations. /// </summary> private static void Keep( SSARewriterContext <FieldRef> context, LoweringData _, Store store) { var newValue = AssembleStructure( context, store.Value.Type as StructureType, store.Value); var newStore = context.Builder.CreateStore( store.Location, store.Target, newValue); context.ReplaceAndRemove(store, newStore); }
/// <summary> /// Converts a load node into an SSA value. /// </summary> private static void Convert( SSARewriterContext <Value> context, ConstructionData data, Load load) { if (data.TryGetConverted(load.Source, out var loadRef)) { var ssaValue = context.GetValue(context.Block, loadRef.Source); if (!loadRef.IsDirect) { ssaValue = context.Builder.CreateGetField( load.Location, ssaValue, loadRef.FieldSpan); } context.ReplaceAndRemove(load, ssaValue); } else if (!load.Uses.HasAny) { context.Remove(load); } }
/// <summary> /// Converts a new get length node into an SSA value. /// </summary> private static void Convert <TConstructionData>( SSARewriterContext <Value> context, TConstructionData data, GetViewLength getViewLength) where TConstructionData : IConstructionData { if (!data.TryGetConverted(getViewLength.View, out var getRef)) { return; } // Get the SSA structure value var ssaValue = context.GetValue(context.Block, getRef.Source); // Get the view length from the first field (index 0) of the wrapped // array structure ssaValue = context.Builder.CreateGetField( getViewLength.Location, ssaValue, new FieldSpan(new FieldAccess(0))); context.ReplaceAndRemove(getViewLength, ssaValue); }