예제 #1
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));
            }
        }
예제 #2
0
 public AsyncStateGroupData(
     AsyncStateGroup asyncStateGroup,
     ContextWrapper context,
     LLVMValueRef function,
     LLVMBasicBlockRef initialBasicBlock,
     LLVMBasicBlockRef continueBasicBlock,
     LLVMBasicBlockRef exitBasicBlock,
     StateFieldValueSource fireCountStateField)
 {
     AsyncStateGroup     = asyncStateGroup;
     Context             = context;
     Function            = function;
     InitialBasicBlock   = initialBasicBlock;
     ContinueBasicBlock  = continueBasicBlock;
     ExitBasicBlock      = exitBasicBlock;
     FireCountStateField = fireCountStateField;
 }
예제 #3
0
        public ExecutionContext(IRebarTargetRuntimeServices runtimeServices)
        {
            _contextWrapper  = new ContextWrapper();
            _runtimeServices = runtimeServices;
            _globalModule    = _contextWrapper.CreateModule("global");
            foreach (ContextFreeModule module in new[]
            {
                CommonModules.FakeDropModule,
                CommonModules.SchedulerModule,
                CommonModules.StringModule,
                CommonModules.OutputModule,
                CommonModules.RangeModule,
                CommonModules.FileModule
            })
            {
                _globalModule.LinkInModule(_contextWrapper.LoadContextFreeModule(module));
            }

            _engine     = _globalModule.CreateMCJITCompilerForModule();
            _targetData = LLVMSharp.LLVM.GetExecutionEngineTargetData(_engine);
        }
예제 #4
0
        internal static LLVMTypeRef TranslateParameterType(this ContextWrapper context, NIType parameterType)
        {
            // TODO: this should probably share code with how we compute the top function LLVM type above
            bool isInput  = parameterType.GetInputParameterPassingRule() != NIParameterPassingRule.NotAllowed,
                 isOutput = parameterType.GetOutputParameterPassingRule() != NIParameterPassingRule.NotAllowed;
            LLVMTypeRef parameterLLVMType = context.AsLLVMType(parameterType.GetDataType());

            if (isInput)   // includes inout parameters
            {
                if (isOutput && !parameterType.GetDataType().IsRebarReferenceType())
                {
                    throw new InvalidOperationException("Inout parameter with non-reference type");
                }
                return(parameterLLVMType);
            }
            if (isOutput)
            {
                return(LLVMTypeRef.PointerType(parameterLLVMType, 0u));
            }
            throw new NotImplementedException("Parameter direction is wrong");
        }
예제 #5
0
 internal static LLVMTypeRef CreateLLVMSliceIteratorType(this ContextWrapper context, LLVMTypeRef elementType)
 {
     return(LLVMTypeRef.StructType(new LLVMTypeRef[] { context.CreateLLVMSliceReferenceType(elementType), context.Int32Type }, false));
 }
예제 #6
0
 internal static LLVMTypeRef CreateLLVMYieldPromiseType(this ContextWrapper context, LLVMTypeRef innerType) => context.StructType(new LLVMTypeRef[] { innerType });
예제 #7
0
 public FunctionAllocationSet(ContextWrapper context)
 {
     Context = context;
 }
예제 #8
0
 public static LLVMTypeRef ScheduledTaskFunctionType(this ContextWrapper context) => LLVMTypeRef.FunctionType(context.VoidType, new[] { context.VoidPointerType() }, false);
예제 #9
0
 public static LLVMValueRef NullVoidPointer(this ContextWrapper context) => LLVMSharp.LLVM.ConstPointerNull(context.VoidPointerType());
예제 #10
0
 public static LLVMTypeRef FakeDropType(this ContextWrapper context) => context.StructType(
     new LLVMTypeRef[]
 {
     context.Int32Type
 });
예제 #11
0
 public static LLVMTypeRef FileHandleType(this ContextWrapper context) => context.StructType(
     new LLVMTypeRef[]
 {
     context.VoidPointerType()
 });
예제 #12
0
 public static LLVMTypeRef RangeIteratorType(this ContextWrapper context) => context.StructType(
     new LLVMTypeRef[]
 {
     context.Int32Type,
     context.Int32Type
 });
예제 #13
0
 public static LLVMTypeRef StringSplitIteratorType(this ContextWrapper context) => context.StructType(
     new LLVMTypeRef[]
 {
     context.StringSliceReferenceType(),
     context.BytePointerType()
 });
예제 #14
0
 public static LLVMTypeRef StringType(this ContextWrapper context) => context.StructType(
     new LLVMTypeRef[]
 {
     context.BytePointerType(),
     context.Int32Type
 });
예제 #15
0
 public CommonModules(ContextWrapper contextWrapper)
 {
     _contextModules = new FunctionMemo <ContextFreeModule, Module>(contextWrapper.LoadContextFreeModule);
 }
예제 #16
0
 internal static LLVMTypeRef TranslateFunctionType(this ContextWrapper context, NIType functionType)
 {
     LLVMTypeRef[] parameterTypes = functionType.GetParameters().Select(context.TranslateParameterType).ToArray();
     return(LLVMSharp.LLVM.FunctionType(context.VoidType, parameterTypes, false));
 }
예제 #17
0
        // TechDebt: for some of the types below, it would be nicer to return named types, which we can do now that we're
        // passing around an LLVM context.
        public static LLVMTypeRef AsLLVMType(this ContextWrapper context, NIType niType)
        {
            switch (niType.GetKind())
            {
            case NITypeKind.UInt8:
            case NITypeKind.Int8:
                return(context.Int8Type);

            case NITypeKind.UInt16:
            case NITypeKind.Int16:
                return(context.Int16Type);

            case NITypeKind.UInt32:
            case NITypeKind.Int32:
                return(context.Int32Type);

            case NITypeKind.UInt64:
            case NITypeKind.Int64:
                return(context.Int64Type);

            case NITypeKind.Boolean:
                return(context.Int1Type);

            case NITypeKind.String:
                return(context.StringType());

            default:
            {
                if (niType.IsRebarReferenceType())
                {
                    NIType referentType = niType.GetReferentType();
                    if (referentType == DataTypes.StringSliceType)
                    {
                        return(context.StringSliceReferenceType());
                    }
                    NIType sliceElementType;
                    if (referentType.TryDestructureSliceType(out sliceElementType))
                    {
                        return(context.CreateLLVMSliceReferenceType(context.AsLLVMType(sliceElementType)));
                    }
                    return(LLVMTypeRef.PointerType(context.AsLLVMType(referentType), 0u));
                }
                if (niType.IsCluster())
                {
                    LLVMTypeRef[] fieldTypes = niType.GetFields().Select(field => context.AsLLVMType(field.GetDataType())).ToArray();
                    return(context.StructType(fieldTypes));
                }
                if (niType == DataTypes.FileHandleType)
                {
                    return(context.FileHandleType());
                }
                if (niType == DataTypes.FakeDropType)
                {
                    return(context.FakeDropType());
                }
                if (niType == DataTypes.RangeIteratorType)
                {
                    return(context.RangeIteratorType());
                }
                if (niType == DataTypes.WakerType)
                {
                    return(context.WakerType());
                }
                NIType innerType;
                if (niType.TryDestructureOptionType(out innerType))
                {
                    return(context.CreateLLVMOptionType(context.AsLLVMType(innerType)));
                }
                if (niType.IsStringSplitIteratorType())
                {
                    return(context.StringSplitIteratorType());
                }
                if (niType.TryDestructureVectorType(out innerType))
                {
                    return(context.CreateLLVMVectorType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructureSliceIteratorType(out innerType) ||
                    niType.TryDestructureSliceMutableIteratorType(out innerType))
                {
                    return(context.CreateLLVMSliceIteratorType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructureSharedType(out innerType))
                {
                    return(context.CreateLLVMSharedType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructureYieldPromiseType(out innerType))
                {
                    return(context.CreateLLVMYieldPromiseType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructureMethodCallPromiseType(out innerType))
                {
                    return(context.CreateLLVMMethodCallPromiseType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructureNotifierReaderType(out innerType))
                {
                    return(context.CreateLLVMNotifierReaderType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructureNotifierReaderPromiseType(out innerType))
                {
                    return(context.CreateLLVMNotifierReaderPromiseType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructureNotifierWriterType(out innerType))
                {
                    return(context.CreateLLVMNotifierWriterType(context.AsLLVMType(innerType)));
                }
                if (niType.TryDestructurePanicResultType(out innerType))
                {
                    return(context.CreateLLVMPanicResultType(context.AsLLVMType(innerType)));
                }
                // TODO: when using typedef classes and unions in FunctionCompiler, the LLVM type should
                // come from a TypeDiagramBuiltPackage.
                if (niType.IsValueClass() && niType.GetFields().Any())
                {
                    LLVMTypeRef[] fieldTypes = niType.GetFields().Select(f => context.AsLLVMType(f.GetDataType())).ToArray();
                    return(context.StructType(fieldTypes));
                }
                if (niType.IsUnion())
                {
                    int maxSize = 4;
                    foreach (NIType field in niType.GetFields())
                    {
                        // TODO: where possible, use a non-array type that matches the max size
                        LLVMTypeRef llvmFieldType = context.AsLLVMType(field.GetDataType());
                        int         fieldSize     = (int)LLVMSharp.LLVM.StoreSizeOfType(LocalTargetInfo.TargetData, llvmFieldType);
                        maxSize = Math.Max(maxSize, fieldSize);
                    }
                    LLVMTypeRef[] structFieldTypes = new LLVMTypeRef[]
                    {
                        context.Int8Type,
                        // TODO: this is incorrect because it does not consider alignment
                        LLVMTypeRef.ArrayType(context.Int8Type, (uint)maxSize)
                    };
                    return(context.StructType(structFieldTypes));
                }
                throw new NotSupportedException("Unsupported type: " + niType);
            }
            }
        }
예제 #18
0
 internal static LLVMTypeRef CreateLLVMPanicResultType(this ContextWrapper context, LLVMTypeRef innerType)
 {
     return(context.StructType(new LLVMTypeRef[] { context.Int1Type, innerType }));
 }
예제 #19
0
 public static LLVMTypeRef BytePointerType(this ContextWrapper context) => LLVMTypeRef.PointerType(context.Int8Type, 0u);
예제 #20
0
 internal static LLVMTypeRef CreateLLVMSliceReferenceType(this ContextWrapper context, LLVMTypeRef innerType)
 {
     return(context.StructType(new LLVMTypeRef[] { LLVMTypeRef.PointerType(innerType, 0u), context.Int32Type }));
 }
예제 #21
0
 public static LLVMValueRef BuildStringSliceReferenceValue(this ContextWrapper context, IRBuilder builder, LLVMValueRef stringPtr, LLVMValueRef length)
 {
     return(builder.BuildSliceReferenceValue(context.StringSliceReferenceType(), stringPtr, length));
 }
예제 #22
0
 internal static LLVMTypeRef CreateLLVMSharedType(this ContextWrapper context, LLVMTypeRef innerType)
 {
     return(LLVMTypeRef.PointerType(context.CreateLLVMRefCountType(innerType), 0u));
 }
예제 #23
0
 public static LLVMTypeRef FunctionCompletionStatusType(ContextWrapper context) => context.Int8Type;
예제 #24
0
 internal static LLVMTypeRef CreateLLVMRefCountType(this ContextWrapper context, LLVMTypeRef innerType)
 {
     return(context.StructType(new LLVMTypeRef[] { context.Int32Type, innerType }));
 }
예제 #25
0
 public FunctionModuleContext(ContextWrapper llvmContext, Module module, FunctionImporter functionImporter)
 {
     LLVMContext      = llvmContext;
     Module           = module;
     FunctionImporter = functionImporter;
 }
예제 #26
0
 public FunctionImporter(ContextWrapper context, Module module)
 {
     _commonModules = new CommonModules(context);
     _module        = module;
 }