Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
            }
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /// <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);
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        /// <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);
        }
Пример #12
0
        /// <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);
        }
Пример #13
0
        /// <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);
        }
Пример #14
0
        /// <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);
            }
        }
Пример #15
0
        /// <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);
        }