Пример #1
0
 /// <summary>
 /// Keeps the IO operation.
 /// </summary>
 protected override void Implement(
     IRContext context,
     Method.Builder methodBuilder,
     BasicBlock.Builder builder,
     WriteToOutput writeToOutput)
 {
 }
Пример #2
0
 /// <summary>
 /// Constructs a new array type lowering.
 /// </summary>
 /// <param name="builder">The parent builder.</param>
 /// <param name="targetAddressSpace">The target address spacce.</param>
 public ArrayTypeLowering(
     Method.Builder builder,
     MemoryAddressSpace targetAddressSpace)
     : base(builder)
 {
     TargetAddressSpace = targetAddressSpace;
 }
Пример #3
0
        /// <summary>
        /// Applies the SSA construction transformation.
        /// </summary>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            // Create scope and try to find SSA-convertible alloca nodes
            var scope = builder.CreateScope(ScopeFlags.AddAlreadyVisitedNodes);

            // Search for convertible allocas
            var allocas = new HashSet <Alloca>();

            scope.ForEachValue <Alloca>(alloca =>
            {
                if (!alloca.IsSimpleAllocation ||
                    alloca.AddressSpace != MemoryAddressSpace.Local ||
                    RequiresAddress(alloca))
                {
                    return;
                }

                allocas.Add(alloca);
            });
            if (allocas.Count < 1)
            {
                return(false);
            }

            // Perform SSA construction
            var ssaBuilder = SSABuilder <Value> .Create(builder, scope);

            return(Rewriter.Rewrite(ssaBuilder, new ConstructionData(allocas)));
        }
Пример #4
0
 /// <summary>
 /// Keeps the debug assertion operation.
 /// </summary>
 protected override void Implement(
     IRContext context,
     Method.Builder methodBuilder,
     BasicBlock.Builder builder,
     DebugAssertOperation debugAssert)
 {
 }
Пример #5
0
        /// <summary>
        /// Performs the internal SSA construction transformation.
        /// </summary>
        /// <param name="builder">The parent meethod builder.</param>
        /// <param name="rewriter">The SSA rewriter to use.</param>
        /// <returns>True, if the transformation could be applied.</returns>
        protected bool PerformTransformation(
            Method.Builder builder,
            SSARewriter <Value, ConstructionData> rewriter)
        {
            // Search for convertible allocas
            var allocas = new HashSet <Alloca>();

            builder.SourceBlocks.ForEachValue <Alloca>(alloca =>
            {
                if (!CanConvert(builder, alloca))
                {
                    return;
                }

                allocas.Add(alloca);
            });
            if (allocas.Count < 1)
            {
                return(false);
            }

            // Perform SSA construction
            var ssaBuilder = SSABuilder <Value> .Create(builder);

            return(rewriter.Rewrite(ssaBuilder, new ConstructionData(allocas)));
        }
Пример #6
0
        /// <summary>
        /// Applies the SSA construction transformation.
        /// </summary>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            // Search for convertible allocas
            var allocas = new HashSet <Alloca>();

            builder.SourceBlocks.ForEachValue <Alloca>(alloca =>
            {
                if (!alloca.IsSimpleAllocation ||
                    alloca.AddressSpace != MemoryAddressSpace.Local ||
                    RequiresAddress(alloca))
                {
                    return;
                }

                allocas.Add(alloca);
            });
            if (allocas.Count < 1)
            {
                return(false);
            }

            // Perform SSA construction
            var ssaBuilder = SSABuilder <Value> .Create(builder);

            return(Rewriter.Rewrite(ssaBuilder, new ConstructionData(allocas)));
        }
Пример #7
0
        /// <summary>
        /// Maps internal <see cref="WriteToOutput"/> values to
        /// <see cref="PrintF(string, void*)"/> method calls.
        /// </summary>
        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            WriteToOutput writeToOutput)
        {
            var location = writeToOutput.Location;

            // Convert to format string constant
            var expressionString = writeToOutput.ToPrintFExpression();
            var expression       = builder.CreatePrimitiveValue(
                location,
                expressionString,
                Encoding.ASCII);

            // Create an argument structure that can be passed via local memory
            var argumentBuilder = builder.CreateDynamicStructure(
                location,
                writeToOutput.Count);

            foreach (Value argument in writeToOutput.Arguments)
            {
                var converted = WriteToOutput.ConvertToPrintFArgument(
                    builder,
                    location,
                    argument);
                argumentBuilder.Add(converted);
            }
            var argumentStructure = argumentBuilder.Seal();

            // Create local alloca to store all data
            var alloca = builder.CreateAlloca(
                location,
                argumentStructure.Type,
                MemoryAddressSpace.Local);

            // Store structure into chunk of local memory
            builder.CreateStore(location, alloca, argumentStructure);

            // Cast alloca to the generic address space to satisfy the requirements of
            // of the printf method
            alloca = builder.CreateAddressSpaceCast(
                location,
                alloca,
                MemoryAddressSpace.Generic);

            // Create a call to the native printf
            var printFMethod = context.Declare(PrintFMethod, out bool _);
            var callBuilder  = builder.CreateCall(location, printFMethod);

            callBuilder.Add(expression);
            callBuilder.Add(alloca);

            // Replace the write node with the call
            callBuilder.Seal();
            builder.Remove(writeToOutput);
        }
Пример #8
0
        /// <summary>
        /// Updates all return types of all affected methods.
        /// </summary>
        /// <param name="builder">The current builder.</param>
        protected sealed override void PrePerformTransformation(Method.Builder builder)
        {
            var typeConverter = CreateLoweringConverter(builder);

            // Update return type
            if (typeConverter.IsTypeDependent(builder.Method.ReturnType))
            {
                builder.UpdateReturnType(typeConverter);
            }
        }
Пример #9
0
        /// <summary>
        /// Maps internal debug assertions to <see cref="AssertFailed(string, string,
        /// int, string, int)"/> method calls.
        /// </summary>

        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            DebugAssertOperation debugAssert)
        {
            var location = debugAssert.Location;

            // Create a call to the debug-implementation wrapper while taking the
            // current source location into account
            var nextBlock  = builder.SplitBlock(debugAssert);
            var innerBlock = methodBuilder.CreateBasicBlock(
                location,
                nameof(AssertFailed));

            builder.CreateIfBranch(
                location,
                debugAssert.Condition,
                nextBlock,
                innerBlock);

            // Create a call to the assert implementation
            var innerBuilder = methodBuilder[innerBlock];
            var assertFailed = innerBuilder.CreateCall(
                location,
                context.Declare(AssertFailedMethod, out var _));

            // Move the debug assertion to this block
            var sourceMessage = debugAssert.Message.ResolveAs <StringValue>();
            var message       = innerBuilder.CreatePrimitiveValue(
                location,
                sourceMessage.String,
                sourceMessage.Encoding);

            assertFailed.Add(message);

            // Append source location information
            var debugLocation = debugAssert.GetLocationInfo();

            assertFailed.Add(
                innerBuilder.CreatePrimitiveValue(location, debugLocation.FileName));
            assertFailed.Add(
                innerBuilder.CreatePrimitiveValue(location, debugLocation.Line));
            assertFailed.Add(
                innerBuilder.CreatePrimitiveValue(location, debugLocation.Method));
            assertFailed.Add(
                innerBuilder.CreatePrimitiveValue(location, 1));

            // Finish the actual assertion call and branch
            assertFailed.Seal();
            innerBuilder.CreateBranch(location, nextBlock);

            // Remove the debug assertion value
            debugAssert.Replace(builder.CreateUndefined());
        }
Пример #10
0
        /// <summary>
        /// Applies the UCE transformation.
        /// </summary>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            var scope = builder.CreateScope();

            // Fold branch targets (if possible)
            bool updated = false;

            foreach (var block in scope)
            {
                // Get the conditional terminator
                var terminator = block.GetTerminatorAs <ConditionalBranch>();
                if (terminator == null || !terminator.CanFold)
                {
                    continue;
                }

                // Fold branch
                var blockBuilder = builder[block];
                terminator.Fold(blockBuilder);

                updated = true;
            }

            // Check for changes
            if (!updated)
            {
                return(false);
            }

            // Find all unreachable blocks
            var updatedScope = builder.CreateScope();

            foreach (var block in scope)
            {
                if (!updatedScope.Contains(block))
                {
                    // Block is unreachable -> remove all operations
                    var blockBuilder = builder[block];
                    blockBuilder.Clear();
                }
            }

            // Update all phi values
            Rewriter.Rewrite(
                updatedScope,
                builder,
                new PhiArgumentRemapper(updatedScope));

            return(true);
        }
Пример #11
0
 internal RewriterProcess(
     Rewriter <TContext, TContextProvider, TContextData, T> rewriter,
     Scope scope,
     Method.Builder builder,
     TContextData contextData,
     T data,
     HashSet <Value> toConvert)
 {
     Rewriter    = rewriter;
     Scope       = scope;
     Builder     = builder;
     ContextData = contextData;
     Data        = data;
     ToConvert   = toConvert;
 }
Пример #12
0
        /// <summary>
        /// Maps internal <see cref="AsAligned"/> values to a debug assertion while
        /// preserving the <see cref="AsAligned"/> value.
        /// </summary>
        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            AsAligned asAligned)
        {
            // Preserve the asAligned operation
            if (!EnableAssertions)
            {
                return;
            }

            // Check the actual pointer alignment
            var location   = asAligned.Location;
            var comparison = builder.CreateCompare(
                location,
                builder.CreateArithmetic(
                    location,
                    builder.CreatePointerAsIntCast(
                        location,
                        asAligned.Source,
                        IntPointerType.BasicValueType),
                    builder.CreateConvert(
                        location,
                        asAligned.AlignmentInBytes,
                        IntPointerType.BasicValueType),
                    BinaryArithmeticKind.Rem),
                builder.CreatePrimitiveValue(
                    location,
                    IntPointerType.BasicValueType,
                    0L),
                CompareKind.Equal);

            // Create the debug assertion
            Value assert = builder.CreateDebugAssert(
                location,
                comparison,
                builder.CreatePrimitiveValue(
                    location,
                    RuntimeErrorMessages.InvalidlyAssumedPointerOrViewAlignment));

            if (assert is DebugAssertOperation assertOperation)
            {
                Implement(context, methodBuilder, builder, assertOperation);
            }
        }
Пример #13
0
            internal CFGBuilder(
                CodeGenerator codeGenerator,
                Method.Builder methodBuilder)
            {
                CodeGenerator = codeGenerator;
                Builder       = methodBuilder;

                var mainEntry = methodBuilder.EntryBlockBuilder;

                EntryBlock = new Block(
                    codeGenerator,
                    mainEntry)
                {
                    InstructionCount = 0
                };
                basicBlockMapping.Add(EntryBlock.BasicBlock, EntryBlock);

                // Create a temporary entry block to ensure that we have a single entry
                // block without any predecessors in all cases
                var internalEntryBlock = new Block(
                    codeGenerator,
                    methodBuilder.CreateBasicBlock(
                        mainEntry.BasicBlock.Location,
                        mainEntry.BasicBlock.Name));

                blockMapping.Add(0, internalEntryBlock);
                basicBlockMapping.Add(internalEntryBlock.BasicBlock, internalEntryBlock);
                BuildBasicBlocks();

                var visited = new HashSet <Block>();

                SetupBasicBlocks(visited, internalEntryBlock, 0);
                WireBlocks();

                // Wire the main entry block with the actual entry block
                mainEntry.CreateBranch(
                    mainEntry.BasicBlock.Location,
                    internalEntryBlock.BasicBlock);

                // Update control-flow structure to refresh all successor/predecessor
                // edge relations
                Blocks = methodBuilder.UpdateControlFlow();
            }