Esempio n. 1
0
        public SynchronousFunctionModuleBuilder(
            FunctionCompilerSharedData sharedData,
            string functionName,
            IEnumerable <AsyncStateGroup> asyncStateGroups)
            : base(sharedData)
        {
            _functionName     = functionName;
            _asyncStateGroups = asyncStateGroups;

            var         parameterTypes   = GetParameterLLVMTypes();
            LLVMTypeRef syncFunctionType = LLVMSharp.LLVM.FunctionType(SharedData.Context.VoidType, parameterTypes.ToArray(), false);

            SyncFunction           = Module.AddFunction(FunctionNames.GetSynchronousFunctionName(functionName), syncFunctionType);
            SyncFunctionEntryBlock = SyncFunction.AppendBasicBlock("entry");

            foreach (AsyncStateGroup asyncStateGroup in asyncStateGroups)
            {
                LLVMBasicBlockRef groupBasicBlock    = SyncFunction.AppendBasicBlock($"{asyncStateGroup.Label}_begin");
                LLVMBasicBlockRef continueBasicBlock = asyncStateGroup.IsSkippable
                    ? SyncFunction.AppendBasicBlock($"{asyncStateGroup.Label}_continue")
                    : default(LLVMBasicBlockRef);
                LLVMBasicBlockRef endBasicBlock = asyncStateGroup.IsSkippable
                    ? SyncFunction.AppendBasicBlock($"{asyncStateGroup.Label}_end")
                    : default(LLVMBasicBlockRef);
                AsyncStateGroups[asyncStateGroup] = new AsyncStateGroupData(asyncStateGroup, SharedData.Context, SyncFunction, groupBasicBlock, continueBasicBlock, endBasicBlock, null);
            }
        }
Esempio n. 2
0
        protected void CreateScheduleCallsForAsyncStateGroups(IRBuilder builder, LLVMValueRef statePointer, IEnumerable <AsyncStateGroup> asyncStateGroups)
        {
            LLVMTypeRef  scheduledTaskType = SharedData.Context.GetScheduledTaskType();
            LLVMValueRef bitCastStatePtr   = builder.CreateBitCast(statePointer, SharedData.Context.VoidPointerType(), "bitCastStatePtr");

            foreach (AsyncStateGroup successor in asyncStateGroups)
            {
                AsyncStateGroupData successorData            = AsyncStateGroups[successor];
                LLVMValueRef        bitCastSuccessorFunction = builder.CreateBitCast(
                    successorData.Function,
                    LLVMTypeRef.PointerType(SharedData.Context.ScheduledTaskFunctionType(), 0u),
                    "bitCastFunction");
                if (!successor.SignaledConditionally && successor.Predecessors.HasMoreThan(1))
                {
                    LLVMValueRef fireCountPtr = ((IAddressableValueSource)successorData.FireCountStateField).GetAddress(builder);
                    builder.CreateCall(
                        SharedData.FunctionImporter.GetImportedCommonFunction(CommonModules.PartialScheduleName),
                        new LLVMValueRef[] { bitCastStatePtr, fireCountPtr, bitCastSuccessorFunction },
                        string.Empty);
                }
                else
                {
                    builder.CreateCall(
                        SharedData.FunctionImporter.GetImportedCommonFunction(CommonModules.ScheduleName),
                        new LLVMValueRef[] { bitCastSuccessorFunction, bitCastStatePtr },
                        string.Empty);
                }
            }
        }
        public override void CompileFunction()
        {
            foreach (AsyncStateGroup asyncStateGroup in _asyncStateGroups)
            {
                AsyncStateGroupData groupData = AsyncStateGroups[asyncStateGroup];
                CompileAsyncStateGroup(asyncStateGroup, new AsyncStateGroupCompilerState(groupData.Function, SharedData.Context.CreateIRBuilder()));
            }

            LLVMValueRef initializeStateFunction = BuildInitializeStateFunction(GetParameterLLVMTypes());
            LLVMValueRef pollFunction            = BuildPollFunction();
        }
        public AsynchronousFunctionModuleBuilder(
            FunctionCompilerSharedData sharedData,
            string functionName,
            IEnumerable <AsyncStateGroup> asyncStateGroups)
            : base(sharedData)
        {
            _functionName     = functionName;
            _asyncStateGroups = asyncStateGroups;

            var fireCountFields = new Dictionary <AsyncStateGroup, StateFieldValueSource>();

            foreach (AsyncStateGroup asyncStateGroup in _asyncStateGroups)
            {
                string groupName = asyncStateGroup.Label;
                if (asyncStateGroup.MaxFireCount > 1)
                {
                    fireCountFields[asyncStateGroup] = SharedData.AllocationSet.CreateStateField($"{groupName}FireCount", NITypes.Int32);
                }
            }
            SharedData.AllocationSet.InitializeStateType(sharedData.Module, functionName);
            LLVMTypeRef groupFunctionType = LLVMTypeRef.FunctionType(
                SharedData.Context.VoidType,
                new LLVMTypeRef[] { LLVMTypeRef.PointerType(SharedData.AllocationSet.StateType, 0u) },
                false);

            var functions = new Dictionary <string, LLVMValueRef>();

            foreach (AsyncStateGroup asyncStateGroup in _asyncStateGroups)
            {
                LLVMValueRef groupFunction;
                if (!functions.TryGetValue(asyncStateGroup.FunctionId, out groupFunction))
                {
                    string groupFunctionName = $"{functionName}::{asyncStateGroup.FunctionId}";
                    groupFunction = Module.AddFunction(groupFunctionName, groupFunctionType);
                    functions[asyncStateGroup.FunctionId] = groupFunction;
                }

                LLVMBasicBlockRef groupBasicBlock    = groupFunction.AppendBasicBlock($"{asyncStateGroup.Label}_begin");
                LLVMBasicBlockRef continueBasicBlock = asyncStateGroup.IsSkippable
                    ? groupFunction.AppendBasicBlock($"{asyncStateGroup.Label}_continue")
                    : default(LLVMBasicBlockRef);
                LLVMBasicBlockRef endBasicBlock = asyncStateGroup.IsSkippable
                    ? groupFunction.AppendBasicBlock($"{asyncStateGroup.Label}_end")
                    : default(LLVMBasicBlockRef);
                StateFieldValueSource fireCountStateField;
                fireCountFields.TryGetValue(asyncStateGroup, out fireCountStateField);
                AsyncStateGroups[asyncStateGroup] = new AsyncStateGroupData(asyncStateGroup, SharedData.Context, groupFunction, groupBasicBlock, continueBasicBlock, endBasicBlock, fireCountStateField);
            }
        }
Esempio n. 5
0
        public override void CompileFunction()
        {
            var syncBuilder = SharedData.Context.CreateIRBuilder();

            syncBuilder.PositionBuilderAtEnd(SyncFunctionEntryBlock);
            string singleFunctionName = _asyncStateGroups.First().FunctionId;

            SharedData.AllocationSet.InitializeFunctionLocalAllocations(singleFunctionName, syncBuilder);
            InitializeParameterAllocations(SyncFunction, syncBuilder);
            syncBuilder.CreateBr(AsyncStateGroups[_asyncStateGroups.First()].InitialBasicBlock);

            foreach (AsyncStateGroup asyncStateGroup in _asyncStateGroups)
            {
                AsyncStateGroupData groupData = AsyncStateGroups[asyncStateGroup];
                CompileAsyncStateGroup(asyncStateGroup, new AsyncStateGroupCompilerState(SyncFunction, syncBuilder));
            }
        }
Esempio n. 6
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;
        }