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); }
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(); } }
public OutputParameterStateFieldValueSource(string allocationName, FunctionAllocationSet allocationSet, int fieldIndex) : base(allocationName, allocationSet, fieldIndex) { }
public StateFieldValueSource(string allocationName, FunctionAllocationSet allocationSet, int fieldIndex) : base(allocationName) { _allocationSet = allocationSet; _fieldIndex = fieldIndex; }
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; }