/// <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); } }
private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, Predicate predicate) { foreach (var(_, fieldAccess) in predicate.Type as StructureType) { // Build a new if predicate which might become dead in the future var trueValue = context.GetValue( context.Block, new FieldRef(predicate.TrueValue, fieldAccess)); var falseValue = context.GetValue( context.Block, new FieldRef(predicate.FalseValue, fieldAccess)); var newPredicate = context.Builder.CreatePredicate( predicate.Location, predicate.Condition, trueValue, falseValue); // Bind the new if predicate context.SetValue( context.Block, new FieldRef(predicate, fieldAccess), newPredicate); } }
/// <summary> /// Lowers structure store operations into distinct stores for each field. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, Store store) { var builder = context.Builder; foreach (var(_, fieldAccess) in store.Value.Type as StructureType) { // Update target address var address = builder.CreateLoadFieldAddress( store.Location, store.Target, new FieldSpan(fieldAccess)); // Load the currently registered SSA value and store it var value = context.GetValue( context.Block, new FieldRef(store.Value, fieldAccess)); var loweredStore = builder.CreateStore( store.Location, address, value); context.MarkConverted(loweredStore); } context.Remove(store); }
/// <summary> /// Converts a store node into an SSA value. /// </summary> private static void Convert( SSARewriterContext <Value> context, ConstructionData data, Store store) { if (!data.TryGetConverted(store.Target, out var storeRef)) { return; } Value ssaValue = store.Value; if (!storeRef.IsDirect) { ssaValue = context.GetValue(context.Block, storeRef.Source); ssaValue = context.Builder.CreateSetField( store.Location, ssaValue, storeRef.FieldSpan, store.Value); } context.SetValue(context.Block, storeRef.Source, ssaValue); context.Remove(store); }
/// <summary> /// Lowers set field operations into separate SSA values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, SetField setField) { foreach (var(_, fieldAccess) in setField.Type as StructureType) { Value value; if (setField.FieldSpan.Contains(fieldAccess)) { // Get value from the source value value = setField.Value; if (value.Type is StructureType) { var getFieldAccess = fieldAccess.Subtract( setField.FieldSpan.Index); value = context.GetValue( context.Block, new FieldRef(value, getFieldAccess)); } } else { // Load the currently registered SSA value value = context.GetValue( context.Block, new FieldRef(setField.ObjectValue, fieldAccess)); } // Bind the mapped SSA value context.SetValue( context.Block, new FieldRef(setField, fieldAccess), value); } context.Remove(setField); }
/// <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); }