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); } }
internal static LLVM.FunctionCompileResult CompileFunctionForLLVM( DfirRoot dfirRoot, CompileCancellationToken cancellationToken, Dictionary <CompilableDefinitionName, bool> calleesIsYielding, Dictionary <CompilableDefinitionName, bool> calleesMayPanic, string compiledFunctionName = "") { // TODO: running this here because it needs to know which callee Functions are yielding/panicking. new AsyncNodeDecompositionTransform(calleesIsYielding, calleesMayPanic, new NodeInsertionTypeUnificationResultFactory()) .Execute(dfirRoot, cancellationToken); ExecutionOrderSortingVisitor.SortDiagrams(dfirRoot); var asyncStateGrouper = new AsyncStateGrouper(); asyncStateGrouper.Execute(dfirRoot, cancellationToken); IEnumerable <AsyncStateGroup> asyncStateGroups = asyncStateGrouper.GetAsyncStateGroups(); using (var contextWrapper = new LLVM.ContextWrapper()) { var module = contextWrapper.CreateModule("module"); var functionImporter = new LLVM.FunctionImporter(contextWrapper, module); var codeGenExpander = new CodeGenExpander( dfirRoot, new LLVM.FunctionModuleContext(contextWrapper, module, functionImporter), calleesMayPanic); asyncStateGroups.ForEach(codeGenExpander.ExpandAsyncStateGroup); #if DEBUG string prettyPrintAsyncStateGroups = asyncStateGroups.PrettyPrintAsyncStateGroups(); #endif bool isYielding = asyncStateGroups.Select(g => g.FunctionId).Distinct().HasMoreThan(1); bool mayPanic = asyncStateGroups.Any(group => group.StartsWithPanicOrContinue); var variableStorage = new LLVM.FunctionVariableStorage(); var allocator = new Allocator(contextWrapper, variableStorage, asyncStateGroups); allocator.Execute(dfirRoot, cancellationToken); compiledFunctionName = string.IsNullOrEmpty(compiledFunctionName) ? FunctionLLVMName(dfirRoot.CompileSpecification.Name) : compiledFunctionName; var parameterInfos = dfirRoot.DataItems.OrderBy(d => d.ConnectorPaneIndex).Select(ToParameterInfo).ToArray(); var sharedData = new LLVM.FunctionCompilerSharedData( contextWrapper, module, parameterInfos, allocator.AllocationSet, variableStorage, functionImporter); var moduleBuilder = isYielding ? new LLVM.AsynchronousFunctionModuleBuilder(sharedData, compiledFunctionName, asyncStateGroups) : (LLVM.FunctionModuleBuilder) new LLVM.SynchronousFunctionModuleBuilder(sharedData, compiledFunctionName, asyncStateGroups); sharedData.VisitationHandler = new LLVM.FunctionCompiler(moduleBuilder, sharedData, codeGenExpander.ReservedIndexCount); moduleBuilder.CompileFunction(); module.VerifyAndThrowIfInvalid(); return(new LLVM.FunctionCompileResult(new LLVM.ContextFreeModule(module), isYielding, mayPanic)); } }
public FunctionCompiler( FunctionModuleBuilder moduleBuilder, FunctionCompilerSharedData sharedData, int codeGenValueIndices) { _moduleBuilder = moduleBuilder; _sharedData = sharedData; ModuleContext = new FunctionModuleContext(_sharedData.Context, _sharedData.Module, _sharedData.FunctionImporter); _codeGenValues = new LLVMValueRef[codeGenValueIndices]; }
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); } }
protected FunctionModuleBuilder(FunctionCompilerSharedData sharedData) { SharedData = sharedData; AsyncStateGroups = new Dictionary <AsyncStateGroup, AsyncStateGroupData>(); }