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 load operations into distinct loads for each field. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, Load load) { var builder = context.Builder; foreach (var(_, fieldAccess) in load.Type as StructureType) { // Update source address var address = builder.CreateLoadFieldAddress( load.Location, load.Source, new FieldSpan(fieldAccess)); // Load value and store its reference in the current block var loweredLoad = builder.CreateLoad(load.Location, address); context.SetValue( context.Block, new FieldRef(load, fieldAccess), loweredLoad); context.MarkConverted(loweredLoad); } context.Remove(load); }
/// <summary> /// Lowers phi values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData data, PhiValue phi) { foreach (var(fieldType, fieldAccess) in phi.Type as StructureType) { // Build a new phi which might become dead in the future var phiBuilder = context.Builder.CreatePhi( phi.Location, fieldType); // Register the lowered phi data.AddPhi(new LoweredPhi( phi, fieldAccess, phiBuilder)); // Bind the new phi value context.SetValue( context.Block, new FieldRef(phi, fieldAccess), phiBuilder.PhiValue); } context.Remove(phi); }
/// <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> /// 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); }
protected static void ConvertAlloca <TConstructionData>( SSARewriterContext <Value> context, TConstructionData data, Alloca alloca, Value initValue) where TConstructionData : IConstructionData { alloca.Assert(data.ContainsAlloca(alloca)); // Bind the init value and remove the allocation from the block context.SetValue(context.Block, alloca, initValue); data.AddConverted(alloca, new FieldRef(alloca)); context.Remove(alloca); }
/// <summary> /// Lowers structure values into separate SSA values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, StructureValue structureValue) { foreach (var(_, fieldAccess) in structureValue.StructureType) { // Build the new target value var value = structureValue[fieldAccess.Index]; // Bind the new SSA value context.SetValue( context.Block, new FieldRef(structureValue, fieldAccess), value); } }
/// <summary> /// Converts an alloca node to its initial SSA value. /// </summary> private static void Convert( SSARewriterContext <Value> context, ConstructionData data, Alloca alloca) { if (!data.ContainsAlloca(alloca)) { return; } var initValue = context.Builder.CreateNull( alloca.Location, alloca.AllocaType); context.SetValue(context.Block, alloca, initValue); data.AddConverted(alloca, new FieldRef(alloca)); context.Remove(alloca); }
/// <summary> /// Lowers null values into separate SSA values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, NullValue nullValue) { foreach (var(fieldType, fieldAccess) in nullValue.Type as StructureType) { // Build the new target value var value = context.Builder.CreateNull( nullValue.Location, fieldType); context.MarkConverted(value); // Bind the new SSA value context.SetValue( context.Block, new FieldRef(nullValue, fieldAccess), value); } }
/// <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); }