Beispiel #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);
            }
        }
Beispiel #2
0
        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));
            }
        }
Beispiel #3
0
 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>();
 }