Example #1
0
 public AsyncStateGroupData(
     AsyncStateGroup asyncStateGroup,
     ContextWrapper context,
     LLVMValueRef function,
     LLVMBasicBlockRef initialBasicBlock,
     LLVMBasicBlockRef continueBasicBlock,
     LLVMBasicBlockRef exitBasicBlock,
     StateFieldValueSource fireCountStateField)
 {
     AsyncStateGroup     = asyncStateGroup;
     Context             = context;
     Function            = function;
     InitialBasicBlock   = initialBasicBlock;
     ContinueBasicBlock  = continueBasicBlock;
     ExitBasicBlock      = exitBasicBlock;
     FireCountStateField = fireCountStateField;
 }
Example #2
0
        public void UnconditionalFrameWithNoInteriorAwaits_GroupAsyncStates_AllFrameAsyncStateGroupsInSameFunction()
        {
            DfirRoot function    = DfirRoot.Create();
            Frame    frame       = Frame.Create(function.BlockDiagram);
            Tunnel   inputTunnel = CreateInputTunnel(frame);

            ConnectConstantToInputTerminal(inputTunnel.InputTerminals[0], NITypes.Int32, false);
            var output = new FunctionalNode(frame.Diagram, Signatures.OutputType);

            Wire.Create(frame.Diagram, inputTunnel.OutputTerminals[0], output.InputTerminals[0]);

            IEnumerable <AsyncStateGroup> asyncStateGroups = GroupAsyncStates(function);

            AsyncStateGroup firstGroup      = asyncStateGroups.First();
            var             groupFunctionId = firstGroup.FunctionId;

            Assert.IsTrue(asyncStateGroups.All(g => g.FunctionId == groupFunctionId));
        }
Example #3
0
        public void LoopFollowedByLoop_GroupAsyncStates_SubsequentLoopStartsInPredecessorLoopTerminalGroup()
        {
            DfirRoot     function        = DfirRoot.Create();
            Loop         firstLoop       = new Loop(function.BlockDiagram);
            BorrowTunnel firstLoopBorrow = CreateBorrowTunnel(firstLoop, BorrowMode.Immutable);

            ConnectConstantToInputTerminal(firstLoopBorrow.InputTerminals[0], NITypes.Int32, false);
            TerminateLifetimeTunnel firstLoopTerminate = firstLoopBorrow.TerminateLifetimeTunnel;
            Loop   secondLoop = new Loop(function.BlockDiagram);
            Tunnel loopTunnel = CreateInputTunnel(secondLoop);

            Wire.Create(function.BlockDiagram, firstLoopTerminate.OutputTerminals[0], loopTunnel.InputTerminals[0]);

            IEnumerable <AsyncStateGroup> asyncStateGroups = GroupAsyncStates(function);

            string          terminalGroupName      = $"loop{firstLoop.UniqueId}_terminalGroup";
            AsyncStateGroup firstLoopTerminalGroup = asyncStateGroups.First(g => g.Label == terminalGroupName);
            AsyncStateGroup secondLoopInitialGroup = asyncStateGroups.First(g => g.GroupContainsStructureTraversalPoint(secondLoop, secondLoop.Diagram, StructureTraversalPoint.BeforeLeftBorderNodes));

            Assert.AreEqual(firstLoopTerminalGroup, secondLoopInitialGroup);
        }
Example #4
0
        public void FrameWithUnwrapOptionTunnelAndNoInteriorAwaits_GroupAsyncStates_AllFrameAsyncStateGroupsInSameFunction()
        {
            DfirRoot           function        = DfirRoot.Create();
            Frame              frame           = Frame.Create(function.BlockDiagram);
            UnwrapOptionTunnel unwrapTunnel    = CreateUnwrapOptionTunnel(frame);
            FunctionalNode     someConstructor = ConnectSomeConstructorToInputTerminal(unwrapTunnel.InputTerminals[0]);

            ConnectConstantToInputTerminal(someConstructor.InputTerminals[0], NITypes.Int32, false);
            var output = new FunctionalNode(frame.Diagram, Signatures.OutputType);

            Wire.Create(frame.Diagram, unwrapTunnel.OutputTerminals[0], output.InputTerminals[0]);

            IEnumerable <AsyncStateGroup> asyncStateGroups = GroupAsyncStates(function);

            AsyncStateGroup frameInitialGroup        = asyncStateGroups.First(g => g.GroupContainsStructureTraversalPoint(frame, frame.Diagram, StructureTraversalPoint.BeforeLeftBorderNodes)),
                            frameDiagramInitialGroup = asyncStateGroups.First(g => g.GroupContainsNode(output)),
                            frameTerminalGroup       = asyncStateGroups.First(g => g.GroupContainsStructureTraversalPoint(frame, frame.Diagram, StructureTraversalPoint.AfterRightBorderNodes));

            Assert.AreEqual(frameInitialGroup.FunctionId, frameDiagramInitialGroup.FunctionId);
            Assert.AreEqual(frameInitialGroup.FunctionId, frameTerminalGroup.FunctionId);
        }
Example #5
0
        protected void CompileAsyncStateGroup(AsyncStateGroup asyncStateGroup, FunctionCompilerState compilerState)
        {
            FunctionCompilerState previousState = CurrentState;

            CurrentGroup = asyncStateGroup;
            CurrentState = compilerState;
            AsyncStateGroupData groupData     = AsyncStateGroups[asyncStateGroup];
            LLVMValueRef        groupFunction = groupData.Function;

            Builder.PositionBuilderAtEnd(groupData.InitialBasicBlock);

            // Here we are assuming that the group whose label matches the function name is also the entry group.
            if (asyncStateGroup.FunctionId == asyncStateGroup.Label && this is AsynchronousFunctionModuleBuilder)
            {
                AllocationSet.InitializeFunctionLocalAllocations(asyncStateGroup.FunctionId, Builder);
            }

            var conditionalContinuation = asyncStateGroup.Continuation as ConditionallyScheduleGroupsContinuation;

            if (conditionalContinuation != null)
            {
                var          continuationConditionValueSource = (IInitializableValueSource)SharedData.VariableStorage.GetValueSourceForVariable(asyncStateGroup.ContinuationCondition);
                LLVMValueRef initialConditionValue            = LLVMSharp.LLVM.ConstNull(SharedData.Context.AsLLVMType(asyncStateGroup.ContinuationCondition.Type));
                continuationConditionValueSource.InitializeValue(Builder, initialConditionValue);
            }

            if (asyncStateGroup.IsSkippable)
            {
                if (asyncStateGroup.FunctionId == asyncStateGroup.Label && this is SynchronousFunctionModuleBuilder)
                {
                    _localDoneAllocationPtr = Builder.CreateAlloca(FunctionAllocationSet.FunctionCompletionStatusType(SharedData.Context), "donePtr");
                    Builder.CreateBr(groupData.ContinueBasicBlock);
                }
                else
                {
                    LLVMValueRef shouldContinue = GenerateContinueStateCheck();
                    Builder.CreateCondBr(shouldContinue, groupData.ContinueBasicBlock, groupData.ExitBasicBlock);
                }
                Builder.PositionBuilderAtEnd(groupData.ContinueBasicBlock);
            }

            groupData.CreateFireCountReset(Builder);

            foreach (Visitation visitation in asyncStateGroup.Visitations)
            {
                visitation.Visit <bool>(SharedData.VisitationHandler);
            }

            var unconditionalContinuation = asyncStateGroup.Continuation as UnconditionallySchduleGroupsContinuation;

            if (unconditionalContinuation != null &&
                !unconditionalContinuation.UnconditionalSuccessors.Any() &&
                this is AsynchronousFunctionModuleBuilder)
            {
                GenerateStoreCompletionState(RuntimeConstants.FunctionCompletedNormallyStatus);
            }

            if (asyncStateGroup.IsSkippable)
            {
                Builder.CreateBr(groupData.ExitBasicBlock);
                Builder.PositionBuilderAtEnd(groupData.ExitBasicBlock);
            }

            bool returnAfterGroup = true;

            if (unconditionalContinuation != null)
            {
                if (unconditionalContinuation.UnconditionalSuccessors.Any())
                {
                    AsyncStateGroup singleSuccessor;
                    if (unconditionalContinuation.UnconditionalSuccessors.TryGetSingleElement(out singleSuccessor) && singleSuccessor.FunctionId == asyncStateGroup.FunctionId)
                    {
                        Builder.CreateBr(AsyncStateGroups[singleSuccessor].InitialBasicBlock);
                        returnAfterGroup = false;
                    }
                    else
                    {
                        CreateInvokeOrScheduleOfSuccessors(unconditionalContinuation.UnconditionalSuccessors);
                    }
                }
                else if (this is AsynchronousFunctionModuleBuilder)
                {
                    GenerateFunctionTerminator();
                }
            }
            if (conditionalContinuation != null)
            {
                LLVMValueRef condition = SharedData.VariableStorage.GetValueSourceForVariable(asyncStateGroup.ContinuationCondition).GetValue(Builder);

                bool isBooleanCondition          = conditionalContinuation.SuccessorConditionGroups.Count == 2;
                bool allSynchronousContinuations = conditionalContinuation.SuccessorConditionGroups.All(group =>
                {
                    AsyncStateGroup singleSuccessor;
                    return(group.TryGetSingleElement(out singleSuccessor) && singleSuccessor.FunctionId == asyncStateGroup.FunctionId);
                });

                if (allSynchronousContinuations)
                {
                    LLVMBasicBlockRef[] initialBlocks = conditionalContinuation.SuccessorConditionGroups
                                                        .Select(g => AsyncStateGroups[g.First()].InitialBasicBlock)
                                                        .ToArray();
                    if (isBooleanCondition)
                    {
                        Builder.CreateCondBr(condition, initialBlocks[1], initialBlocks[0]);
                    }
                    else
                    {
                        LLVMValueRef conditionSwitch = Builder.CreateSwitch(condition, initialBlocks[0], (uint)(initialBlocks.Length - 1));
                        for (int i = 1; i < initialBlocks.Length; ++i)
                        {
                            conditionSwitch.AddCase(SharedData.Context.AsLLVMValue((byte)i), initialBlocks[i]);
                        }
                    }
                    returnAfterGroup = false;
                }
                else
                {
                    LLVMBasicBlockRef[] continuationConditionBlocks = Enumerable.Range(0, conditionalContinuation.SuccessorConditionGroups.Count)
                                                                      .Select(i => groupFunction.AppendBasicBlock($"continuationCondition{i}"))
                                                                      .ToArray();
                    LLVMBasicBlockRef exitBlock = groupFunction.AppendBasicBlock("exit");
                    if (isBooleanCondition)
                    {
                        Builder.CreateCondBr(condition, continuationConditionBlocks[1], continuationConditionBlocks[0]);
                    }
                    else
                    {
                        LLVMValueRef conditionSwitch = Builder.CreateSwitch(condition, continuationConditionBlocks[0], (uint)(conditionalContinuation.SuccessorConditionGroups.Count - 1));
                        for (int i = 1; i < continuationConditionBlocks.Length; ++i)
                        {
                            conditionSwitch.AddCase(SharedData.Context.AsLLVMValue((byte)i), continuationConditionBlocks[i]);
                        }
                    }

                    for (int i = 0; i < continuationConditionBlocks.Length; ++i)
                    {
                        Builder.PositionBuilderAtEnd(continuationConditionBlocks[i]);
                        CreateInvokeOrScheduleOfSuccessors(conditionalContinuation.SuccessorConditionGroups[i]);
                        Builder.CreateBr(exitBlock);
                    }

                    Builder.PositionBuilderAtEnd(exitBlock);
                }
            }

            if (returnAfterGroup)
            {
                Builder.CreateRetVoid();
            }

            CurrentGroup = null;
            CurrentState = previousState;
        }