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); } }
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); } }
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)); } }
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; }