示例#1
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);
        }
示例#2
0
        /// <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);
        }
示例#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>
        /// 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);
            }
        }
示例#5
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);
        }
示例#6
0
        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);
            }
        }
示例#7
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);
        }
示例#8
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);
        }
示例#9
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);
        }
示例#10
0
 /// <summary>
 /// Keeps structure load operations.
 /// </summary>
 private static void Keep(
     SSARewriterContext <FieldRef> context,
     LoweringData _,
     Load load) =>
 DisassembleStructure(
     context,
     load.Type as StructureType,
     load);
示例#11
0
 /// <summary>
 /// Lowers parameter values containing structure values.
 /// </summary>
 private static void Lower(
     SSARewriterContext <FieldRef> context,
     LoweringData _,
     Parameter value) =>
 DisassembleStructure(
     context,
     value.Type as StructureType,
     value);
示例#12
0
 /// <summary>
 /// Lowers generic values containing structure types that cannot be rewritten.
 /// </summary>
 private static void Keep(
     SSARewriterContext <FieldRef> context,
     LoweringData _,
     Value value) =>
 DisassembleStructure(
     context,
     value.Type.As <StructureType>(value),
     value);
示例#13
0
 /// <summary>
 /// Builds a new structure value during lowering of a source value.
 /// </summary>
 private static Value AssembleStructure(
     SSARewriterContext <FieldRef> context,
     StructureType structureType,
     Value value) =>
 context.AssembleStructure(
     structureType,
     value,
     (ctx, source, fieldAccess) =>
     // Load the currently registered SSA value
     ctx.GetValue(ctx.Block, new FieldRef(source, fieldAccess)));
示例#14
0
 /// <summary>
 /// Lowers sub-warp shuffles.
 /// </summary>
 private static void Lower(
     SSARewriterContext <FieldRef> context,
     LoweringData _,
     SubWarpShuffle value) =>
 LowerThreadValue <
     SubWarpShuffle,
     LowerThreadIntrinsics.SubWarpShuffleLowering>(
     context,
     value.Type as StructureType,
     value);
示例#15
0
 /// <summary>
 /// Lowers warp shuffles.
 /// </summary>
 private static void Lower(
     SSARewriterContext <FieldRef> context,
     LoweringData _,
     Broadcast value) =>
 LowerThreadValue <
     Broadcast,
     LowerThreadIntrinsics.BroadcastLowering>(
     context,
     value.Type as StructureType,
     value);
示例#16
0
 /// <summary>
 /// Registers all structure values in the current SSA builder.
 /// </summary>
 private static void DisassembleStructure(
     SSARewriterContext <FieldRef> context,
     StructureType structureType,
     Value value) =>
 context.DisassembleStructure(
     structureType,
     value,
     (ctx, source, getField, fieldAccess) =>
     ctx.SetValue(
         ctx.Block,
         new FieldRef(value, fieldAccess),
         getField));
示例#17
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);
        }
示例#18
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);
        }
示例#19
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);
        }
示例#20
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);
        }
示例#21
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);
        }
示例#22
0
        /// <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);
        }
示例#23
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);

            ConvertAlloca(context, data, alloca, initValue);
        }
示例#24
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);
        }
示例#25
0
        /// <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);
            }
        }
示例#26
0
        /// <summary>
        /// Converts an alloca node to its initial SSA value.
        /// </summary>
        private static void Convert <TConstructionData>(
            SSARewriterContext <Value> context,
            TConstructionData data,
            Alloca alloca)
            where TConstructionData : IConstructionData
        {
            if (!data.ContainsAlloca(alloca))
            {
                return;
            }
            alloca.Assert(!alloca.IsSimpleAllocation);

            // Get the builder and the associated array length value
            var builder          = context.Builder;
            var arrayLengthValue = alloca.ArrayLength.ResolveAs <PrimitiveValue>();

            alloca.AssertNotNull(arrayLengthValue);
            int arrayLength = arrayLengthValue.Int32Value;

            // Create a structure with the appropriate number of fields that correspond
            // to the current array length
            var allocaTypeBuilder = builder.CreateStructureType(arrayLength + 1);

            // Append array length
            allocaTypeBuilder.Add(builder.GetPrimitiveType(BasicValueType.Int32));
            // Append all virtual fields
            for (int i = 0; i < arrayLength; ++i)
            {
                allocaTypeBuilder.Add(alloca.AllocaType);
            }
            var allocationType = allocaTypeBuilder.Seal();

            // Initialize the structure value
            var initValue = builder.CreateNull(alloca.Location, allocationType);

            // ... and set the array length
            initValue = builder.CreateSetField(
                alloca.Location,
                initValue,
                new FieldSpan(new FieldAccess(0)),
                builder.CreateConvertToInt32(alloca.Location, arrayLengthValue));
            ConvertAlloca(context, data, alloca, initValue);
        }
示例#27
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);
        }
示例#28
0
        /// <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);
            }
        }
示例#29
0
        /// <summary>
        /// Lowers return terminators returning structure values.
        /// </summary>
        private static void Lower(
            SSARewriterContext <FieldRef> context,
            LoweringData _,
            ReturnTerminator value)
        {
            // Move the block builder to a valid insert position in the source block
            var blockBuilder = context.GetMethodBuilder()[value.BasicBlock];

            blockBuilder.SetupInsertPositionToEnd();

            // Assemble return value
            Value returnValue    = value.ReturnValue;
            var   returnType     = returnValue.Type.As <StructureType>(value);
            var   newReturnValue = AssembleStructure(
                context.SpecializeBuilder(blockBuilder),
                returnType,
                returnValue);

            // Replace return terminator with a new terminator
            context.Builder.Terminator = context.Builder.CreateReturn(
                value.Location,
                newReturnValue);
        }
示例#30
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);
            }
        }