Exemple #1
0
 public LocalAllocationValueSource(string allocationName, FunctionAllocationSet allocationSet, string functionName, int allocationIndex)
     : base(allocationName)
 {
     _allocationSet   = allocationSet;
     _functionName    = functionName;
     _allocationIndex = allocationIndex;
 }
 public FunctionCompilerSharedData(
     ContextWrapper context,
     Module module,
     IReadOnlyList <ParameterInfo> orderedParameters,
     FunctionAllocationSet allocationSet,
     FunctionVariableStorage variableStorage,
     FunctionImporter functionImporter)
 {
     Context           = context;
     Module            = module;
     OrderedParameters = orderedParameters;
     AllocationSet     = allocationSet;
     VariableStorage   = variableStorage;
     FunctionImporter  = functionImporter;
     ModuleContext     = new FunctionModuleContext(context, module, functionImporter);
 }
Exemple #3
0
        internal static void BuildMethodCallPromisePollFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef methodCallPromisePollFunction)
        {
            NIType optionPromiseResultType = signature.GetParameters().ElementAt(2).GetDataType();
            NIType promiseResultType;

            optionPromiseResultType.TryDestructureOptionType(out promiseResultType);
            NIType resultType;
            bool   mayPanic = promiseResultType.TryDestructurePanicResultType(out resultType);

            LLVMBasicBlockRef entryBlock          = methodCallPromisePollFunction.AppendBasicBlock("entry"),
                              targetDoneBlock     = methodCallPromisePollFunction.AppendBasicBlock("targetDone"),
                              targetNotDoneBlock  = methodCallPromisePollFunction.AppendBasicBlock("targetNotDone");
            LLVMBasicBlockRef targetPanickedBlock = mayPanic
                ? methodCallPromisePollFunction.AppendBasicBlock("targetPanicked")
                : default(LLVMBasicBlockRef);
            var builder = moduleContext.LLVMContext.CreateIRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);
            LLVMTypeRef stateType = moduleContext.LLVMContext.StructType(new[]
            {
                FunctionAllocationSet.FunctionCompletionStatusType(moduleContext.LLVMContext),
                moduleContext.LLVMContext.WakerType(),
            });

            LLVMValueRef promisePtr              = methodCallPromisePollFunction.GetParam(0u),
                         promise                 = builder.CreateLoad(promisePtr, "promise"),
                         stateVoidPtr            = builder.CreateExtractValue(promise, MethodCallPromiseStatePtrFieldIndex, "stateVoidPtr"),
                         result                  = builder.CreateExtractValue(promise, MethodCallPromiseOutputFieldIndex, "result"),
                         statePtr                = builder.CreateBitCast(stateVoidPtr, LLVMTypeRef.PointerType(stateType, 0u), "statePtr"),
                         state                   = builder.CreateLoad(statePtr, "state"),
                         functionCompletionState = builder.CreateExtractValue(state, 0u, "functionCompletionState"),
                         optionResultOutputPtr   = methodCallPromisePollFunction.GetParam(2u);
            LLVMTypeRef optionResultOutputType   = optionResultOutputPtr.TypeOf().GetElementType();

            uint         switchCases           = mayPanic ? 2u : 1u;
            LLVMValueRef completionStateSwitch = builder.CreateSwitch(functionCompletionState, targetNotDoneBlock, switchCases);

            completionStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(RuntimeConstants.FunctionCompletedNormallyStatus), targetDoneBlock);
            if (mayPanic)
            {
                completionStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(RuntimeConstants.FunctionPanickedStatus), targetPanickedBlock);
            }

            builder.PositionBuilderAtEnd(targetDoneBlock);
            builder.CreateFree(stateVoidPtr);
            LLVMValueRef finalResult = mayPanic ? builder.CreateInsertValue(result, moduleContext.LLVMContext.AsLLVMValue(true), 0u, "okResult") : result;
            LLVMValueRef someResult  = moduleContext.LLVMContext.BuildOptionValue(builder, optionResultOutputType, finalResult);

            builder.CreateStore(someResult, optionResultOutputPtr);
            builder.CreateRetVoid();

            builder.PositionBuilderAtEnd(targetNotDoneBlock);
            LLVMValueRef waker            = methodCallPromisePollFunction.GetParam(1u),
                         wakerFunctionPtr = builder.CreateExtractValue(waker, 0u, "wakerFunctionPtr"),
                         wakerStatePtr    = builder.CreateExtractValue(waker, 1u, "wakerStatePtr"),
                         pollFunctionPtr  = builder.CreateExtractValue(promise, MethodCallPromisePollFunctionPtrFieldIndex, "pollFunctionPtr");

            builder.CreateCall(pollFunctionPtr, new LLVMValueRef[] { stateVoidPtr, wakerFunctionPtr, wakerStatePtr }, string.Empty);
            LLVMValueRef noneResult = moduleContext.LLVMContext.BuildOptionValue(builder, optionResultOutputType, null);

            builder.CreateStore(noneResult, optionResultOutputPtr);
            builder.CreateRetVoid();

            if (mayPanic)
            {
                builder.PositionBuilderAtEnd(targetPanickedBlock);
                LLVMValueRef panicResult     = builder.CreateInsertValue(result, moduleContext.LLVMContext.AsLLVMValue(false), 0u, "panicResult"),
                             somePanicResult = moduleContext.LLVMContext.BuildOptionValue(builder, optionResultOutputType, panicResult);
                builder.CreateStore(somePanicResult, optionResultOutputPtr);
                builder.CreateRetVoid();
            }
        }
Exemple #4
0
 public OutputParameterStateFieldValueSource(string allocationName, FunctionAllocationSet allocationSet, int fieldIndex)
     : base(allocationName, allocationSet, fieldIndex)
 {
 }
Exemple #5
0
 public StateFieldValueSource(string allocationName, FunctionAllocationSet allocationSet, int fieldIndex)
     : base(allocationName)
 {
     _allocationSet = allocationSet;
     _fieldIndex    = fieldIndex;
 }
Exemple #6
0
 public OutputParameterLocalAllocationValueSource(string allocationName, FunctionAllocationSet allocationSet, string functionName, int allocationIndex)
     : base(allocationName, allocationSet, functionName, allocationIndex)
 {
 }
        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;
        }