/// <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> /// 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); }
/// <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> /// Converts a load node into an SSA value. /// </summary> private static void Convert <TConstructionData>( SSARewriterContext <Value> context, TConstructionData data, LoadElementAddress loadElementAddress) where TConstructionData : IConstructionData { if (!data.TryGetConverted(loadElementAddress.Source, out var leaRef)) { return; } // Get the primitive constant field offset loadElementAddress.Assert(loadElementAddress.IsViewAccess); var fieldOffset = loadElementAddress.Offset.ResolveAs <PrimitiveValue>(); loadElementAddress.AssertNotNull(fieldOffset); // Map the field index + 1 to skip the initial array length int fieldIndex = fieldOffset.Int32Value + 1; data.AddConverted( loadElementAddress, leaRef.Access(new FieldAccess(fieldIndex))); context.Remove(loadElementAddress); }
/// <summary> /// Converts an address-space cast into an SSA binding. /// </summary> private static void Convert( SSARewriterContext <Value> context, ConstructionData data, AddressSpaceCast addressSpaceCast) { if (!data.TryGetConverted(addressSpaceCast.Value, out var castRef)) { return; } data.AddConverted(addressSpaceCast, castRef); context.Remove(addressSpaceCast); }
/// <summary> /// Converts a new view into an SSA value. /// </summary> private static void Convert <TConstructionData>( SSARewriterContext <Value> context, TConstructionData data, NewView newView) where TConstructionData : IConstructionData { if (!data.TryGetConverted(newView.Pointer, out var newViewRef)) { return; } data.AddConverted(newView, newViewRef); context.Remove(newView); }
/// <summary> /// Converts an address-space cast into an SSA binding. /// </summary> protected static void Convert <TConstructionData>( SSARewriterContext <Value> context, TConstructionData data, AddressSpaceCast addressSpaceCast) where TConstructionData : IConstructionData { if (!data.TryGetConverted(addressSpaceCast.Value, out var castRef)) { return; } data.AddConverted(addressSpaceCast, castRef); context.Remove(addressSpaceCast); }
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> /// Converts a field-address operation into an SSA binding. /// </summary> private static void Convert( SSARewriterContext <Value> context, ConstructionData data, LoadFieldAddress loadFieldAddress) { if (!data.TryGetConverted(loadFieldAddress.Source, out var fieldRef)) { return; } data.AddConverted( loadFieldAddress, fieldRef.Access(loadFieldAddress.FieldSpan)); context.Remove(loadFieldAddress); }
/// <summary> /// Converts a field-address operation into an SSA binding. /// </summary> protected static void Convert <TConstructionData>( SSARewriterContext <Value> context, TConstructionData data, LoadFieldAddress loadFieldAddress) where TConstructionData : IConstructionData { if (!data.TryGetConverted(loadFieldAddress.Source, out var fieldRef)) { return; } data.AddConverted( loadFieldAddress, fieldRef.Access(loadFieldAddress.FieldSpan)); context.Remove(loadFieldAddress); }
/// <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> /// 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> /// 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); }