Esempio n. 1
0
        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);
                }
            }
        }
Esempio n. 2
0
        public LLVMModuleRef GenerateLLVM()
        {
            LLVMTypeRef stringType = LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0);

            var printfArguments = new LLVMTypeRef[] { stringType };
            var printf          = LLVM.AddFunction(_module, "printf", LLVM.FunctionType(LLVMTypeRef.Int32Type(), printfArguments, LLVMBoolTrue));

            LLVM.SetLinkage(printf, LLVMLinkage.LLVMExternalLinkage);

            var scanfArguments = new LLVMTypeRef[] { stringType };
            var scanf          = LLVM.AddFunction(_module, "scanf", LLVM.FunctionType(LLVMTypeRef.Int32Type(), scanfArguments, LLVMBoolTrue));

            LLVM.SetLinkage(scanf, LLVMLinkage.LLVMExternalLinkage);

            // Generate functions, globals, etc.
            for (int i = 0; i < _statements.Count; i++)
            {
                _statements[i].Accept(this);
            }

            // Generate everything inside the functions
            while (_valueStack.Count > 0)
            {
                _valueStack.Peek().Item2.Accept(this);
            }

            return(_module);
        }
Esempio n. 3
0
        public static LLVMValueRef CreateMalloc(this FunctionModuleContext moduleContext, IRBuilder builder, LLVMTypeRef type, string name)
        {
            LLVMValueRef mallocFunction = moduleContext.FunctionImporter.GetCachedFunction("malloc", moduleContext.CreateMallocFunction),
                         mallocCall     = builder.CreateCall(mallocFunction, new LLVMValueRef[] { type.SizeOf() }, "malloCcall");

            return(builder.CreateBitCast(mallocCall, LLVMTypeRef.PointerType(type, 0u), name));
        }
Esempio n. 4
0
 public static LLVMTypeRef WakerType(this ContextWrapper context) => context.StructType(
     new LLVMTypeRef[]
 {
     // task function pointer
     LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u),
     // task state
     context.VoidPointerType()
 });
Esempio n. 5
0
 public static void MakePointer(LLVMValueRef pValue, ref LLVMTypeRef pType)
 {
     //We want to make pType match pValue, so we only make it a pointer if pValue is also a pointer
     if (IsPointer(pValue))
     {
         pType = LLVMTypeRef.PointerType(pType, 0);
     }
 }
Esempio n. 6
0
 internal static LLVMTypeRef CreateLLVMNotifierWriterType(this ContextWrapper context, LLVMTypeRef innerType)
 {
     return(context.StructType(
                new LLVMTypeRef[]
     {
         LLVMTypeRef.PointerType(context.CreateLLVMRefCountType(context.CreateLLVMNotifierSharedDataType(innerType)), 0u)
     },
                false));
 }
 public static LLVMTypeRef PollFunctionType(ContextWrapper context) => LLVMTypeRef.FunctionType(
     context.VoidType,
     new LLVMTypeRef[]
 {
     context.VoidPointerType(),
     LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u),
     context.VoidPointerType()
 },
     false);
Esempio n. 8
0
 private static LLVMTypeRef MethodPollFunctionType(this ContextWrapper context) => LLVMTypeRef.FunctionType(
     context.VoidType,
     new LLVMTypeRef[]
 {
     context.VoidPointerType(),
     LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u),
     context.VoidPointerType()
 },
     false);
Esempio n. 9
0
        public static LLVMValueRef CreateArrayMalloc(this FunctionModuleContext moduleContext, IRBuilder builder, LLVMTypeRef type, LLVMValueRef size, string name)
        {
            LLVMValueRef bitCastSize    = builder.CreateZExtOrBitCast(size, moduleContext.LLVMContext.Int64Type, "bitCastSize"),
                         mallocSize     = builder.CreateMul(type.SizeOf(), bitCastSize, "mallocSize"),
                         mallocFunction = moduleContext.FunctionImporter.GetCachedFunction("malloc", moduleContext.CreateMallocFunction),
                         mallocCall     = builder.CreateCall(mallocFunction, new LLVMValueRef[] { mallocSize }, "malloCcall");

            return(builder.CreateBitCast(mallocCall, LLVMTypeRef.PointerType(type, 0u), name));
        }
Esempio n. 10
0
 internal static LLVMTypeRef CreateLLVMMethodCallPromiseType(this ContextWrapper context, LLVMTypeRef innerType)
 {
     return(context.StructType(new LLVMTypeRef[]
     {
         LLVMTypeRef.PointerType(context.MethodPollFunctionType(), 0u),
         context.VoidPointerType(),
         innerType,
     }));
 }
Esempio n. 11
0
        public static LLVMTypeRef AsLLVMType(this NIType niType)
        {
            if (niType.IsInteger())
            {
                switch (niType.GetKind())
                {
                case NITypeKind.UInt8:
                case NITypeKind.Int8:
                    return(LLVMTypeRef.Int8Type());

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

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

                case NITypeKind.UInt64:
                case NITypeKind.Int64:
                    return(LLVMTypeRef.Int64Type());
                }
            }
            if (niType.IsBoolean())
            {
                return(LLVMTypeRef.Int1Type());
            }
            if (niType.IsString())
            {
                return(StringType);
            }
            if (niType.IsRebarReferenceType())
            {
                NIType referentType = niType.GetReferentType();
                if (referentType == DataTypes.StringSliceType)
                {
                    return(StringSliceReferenceType);
                }
                return(LLVMTypeRef.PointerType(referentType.AsLLVMType(), 0u));
            }
            if (niType == DataTypes.FileHandleType)
            {
                return(FileHandleType);
            }
            NIType innerType;

            if (niType.TryDestructureOptionType(out innerType))
            {
                return(CreateLLVMOptionType(innerType.AsLLVMType()));
            }
            if (niType == DataTypes.RangeIteratorType)
            {
                return(RangeIteratorType);
            }
            throw new NotSupportedException("Unsupported type: " + niType);
        }
Esempio n. 12
0
 public static LLVMTypeRef GetScheduledTaskType(this ContextWrapper context)
 {
     return(context.GetCachedStructType("scheduled_task", () => new[]
     {
         // task function pointer
         LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u),
         // task state
         context.VoidPointerType()
     }));
 }
Esempio n. 13
0
 internal static LLVMTypeRef CreateLLVMVectorType(this ContextWrapper context, LLVMTypeRef elementType)
 {
     return(context.StructType(
                // { allocationPtr, size, capacity }
                new LLVMTypeRef[]
     {
         LLVMTypeRef.PointerType(elementType, 0u),
         context.Int32Type,
         context.Int32Type
     },
                false));
 }
Esempio n. 14
0
        bool ICodeGenElementVisitor <bool> .VisitGetVariantFieldValue(GetVariantFieldValue getVariantFieldValue)
        {
            LLVMTypeRef  fieldLLVMType        = Context.AsLLVMType(getVariantFieldValue.FieldType);
            LLVMValueRef variantAddress       = _codeGenValues[getVariantFieldValue.VariantAddressIndex],
                         variantValueFieldPtr = Builder.CreateStructGEP(variantAddress, 1u, "variantValueFieldPtr"),
                         bitCastFieldPtr      = Builder.CreateBitCast(
                variantValueFieldPtr,
                LLVMTypeRef.PointerType(fieldLLVMType, 0u),
                "bitCastFieldPtr");

            _codeGenValues[getVariantFieldValue.FieldValueIndex] = Builder.CreateLoad(bitCastFieldPtr, "fieldValue");
            return(true);
        }
        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);
            }
        }
Esempio n. 16
0
        internal static void BuildCreateYieldPromiseFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef createYieldPromiseFunction)
        {
            LLVMTypeRef valueType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()),
             valueReferenceType   = LLVMTypeRef.PointerType(valueType, 0u),
             yieldPromiseType     = moduleContext.LLVMContext.CreateLLVMYieldPromiseType(valueReferenceType);

            LLVMBasicBlockRef entryBlock = createYieldPromiseFunction.AppendBasicBlock("entry");
            var builder = moduleContext.LLVMContext.CreateIRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);
            LLVMValueRef value        = createYieldPromiseFunction.GetParam(0u),
                         yieldPromise = builder.BuildStructValue(yieldPromiseType, new[] { value });

            builder.CreateStore(yieldPromise, createYieldPromiseFunction.GetParam(1u));
            builder.CreateRetVoid();
        }
Esempio n. 17
0
        public static LLVMTypeRef LlvmTypeFromName(string name)
        {
            // TODO: Implement functionality for pointer types.
            // Special case for string type.
            if (name == TypeName.String)
            {
                return(LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0));
            }
            // Otherwise, use LLVM type map.
            else if (LlvmTypeMap.ContainsKey(name))
            {
                return(LlvmTypeMap[name]());
            }

            // Throw an exception.
            throw new Exception($"Non-registered type resolver for type '{name}'");
        }
Esempio n. 18
0
        internal static void GenerateWakerFromCurrentGroup(IRBuilder builder, ICodeGenValueStorage valueStorage, int outputIndex)
        {
            var          functionCompiler            = (FunctionCompiler)valueStorage;
            LLVMValueRef bitCastCurrentGroupFunction = builder.CreateBitCast(
                functionCompiler._moduleBuilder.CurrentGroupData.Function,
                LLVMTypeRef.PointerType(functionCompiler.Context.ScheduledTaskFunctionType(), 0u),
                "bitCastCurrentGroupFunction"),
                         bitCastStatePtr = builder.CreateBitCast(
                functionCompiler.AllocationSet.StatePointer,
                functionCompiler.Context.VoidPointerType(),
                "bitCastStatePtr"),
                         waker = builder.BuildStructValue(
                functionCompiler.Context.AsLLVMType(DataTypes.WakerType),
                new LLVMValueRef[] { bitCastCurrentGroupFunction, bitCastStatePtr },
                "waker");

            valueStorage[outputIndex] = waker;
        }
Esempio n. 19
0
        private static void CreateFileModule(Module fileModule)
        {
            CommonExternalFunctions externalFunctions = new CommonExternalFunctions(fileModule);

            CommonModuleSignatures[OpenFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMExtensions.StringSliceReferenceType,
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType.CreateLLVMOptionType(), 0),
            },
                false);
            BuildOpenFileHandleFunction(fileModule, externalFunctions);

            CommonModuleSignatures[ReadLineFromFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0),
                LLVMTypeRef.PointerType(LLVMExtensions.StringType.CreateLLVMOptionType(), 0),
            },
                false);
            BuildReadLineFromFileHandleFunction(fileModule, externalFunctions);

            CommonModuleSignatures[WriteStringToFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0),
                LLVMExtensions.StringSliceReferenceType,
            },
                false);
            BuildWriteStringToFileHandleFunction(fileModule, externalFunctions);

            CommonModuleSignatures[DropFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0),
            },
                false);
            BuildDropFileHandleFunction(fileModule, externalFunctions);
        }
Esempio n. 20
0
        private static LLVMValueRef BuildDecrementRefCountFunction(FunctionModuleContext moduleContext, string functionName, NIType valueType)
        {
            LLVMTypeRef functionType = LLVMTypeRef.FunctionType(
                moduleContext.LLVMContext.VoidType,
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(moduleContext.LLVMContext.CreateLLVMRefCountType(moduleContext.LLVMContext.AsLLVMType(valueType)), 0u)
            },
                false);
            LLVMValueRef      decrementRefCountFunction = moduleContext.Module.AddFunction(functionName, functionType);
            LLVMBasicBlockRef entryBlock           = decrementRefCountFunction.AppendBasicBlock("entry"),
                              noRefsRemainingBlock = decrementRefCountFunction.AppendBasicBlock("noRefsRemaining"),
                              endBlock             = decrementRefCountFunction.AppendBasicBlock("end");
            var builder = moduleContext.LLVMContext.CreateIRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);
            LLVMValueRef refCountObjectPtr = decrementRefCountFunction.GetParam(0u),
                         referenceCountPtr = builder.CreateStructGEP(refCountObjectPtr, 0u, "referenceCountPtr"),
                         one = moduleContext.LLVMContext.AsLLVMValue(1),
                         previousReferenceCount = builder.CreateAtomicRMW(
                LLVMAtomicRMWBinOp.LLVMAtomicRMWBinOpSub,
                referenceCountPtr,
                one,
                // Since the decrement to the reference count does not have any effect until after we branch,
                // we only need monotonic ordering here.
                // See the documentation about atomic orderings here: https://llvm.org/docs/LangRef.html#atomic-memory-ordering-constraints
                LLVMAtomicOrdering.LLVMAtomicOrderingMonotonic,
                false),
                         noRefsRemaining = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, previousReferenceCount, one, "noRefsRemaining");

            builder.CreateCondBr(noRefsRemaining, noRefsRemainingBlock, endBlock);

            builder.PositionBuilderAtEnd(noRefsRemainingBlock);
            moduleContext.CreateDropCallIfDropFunctionExists(builder, valueType, b => b.CreateStructGEP(refCountObjectPtr, 1u, "valuePtr"));
            builder.CreateFree(refCountObjectPtr);
            builder.CreateBr(endBlock);

            builder.PositionBuilderAtEnd(endBlock);
            builder.CreateRetVoid();
            return(decrementRefCountFunction);
        }
Esempio n. 21
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");
        }
Esempio n. 22
0
        private static void CreateRangeModule(Module rangeModule)
        {
            CommonModuleSignatures[RangeIteratorNextName] = LLVMSharp.LLVM.FunctionType(
                LLVMTypeRef.Int32Type().CreateLLVMOptionType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(LLVMExtensions.RangeIteratorType, 0)
            },
                false);
            BuildRangeIteratorNextFunction(rangeModule);

            CommonModuleSignatures[CreateRangeIteratorName] = LLVMSharp.LLVM.FunctionType(
                LLVMTypeRef.Int32Type().CreateLLVMOptionType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.Int32Type(),
                LLVMTypeRef.Int32Type(),
                LLVMTypeRef.PointerType(LLVMExtensions.RangeIteratorType, 0)
            },
                false);
            BuildCreateRangeIteratorFunction(rangeModule);
        }
Esempio n. 23
0
        protected IEnumerable <LLVMTypeRef> GetParameterLLVMTypes()
        {
            foreach (var parameter in SharedData.OrderedParameters)
            {
                NIType parameterType = parameter.ParameterVariable.Type;
                switch (parameter.Direction)
                {
                case Direction.Input:
                    yield return(SharedData.Context.AsLLVMType(parameterType));

                    break;

                case Direction.Output:
                    yield return(LLVMTypeRef.PointerType(SharedData.Context.AsLLVMType(parameterType), 0u));

                    break;

                default:
                    throw new NotImplementedException("Can only handle in and out parameters");
                }
            }
        }
Esempio n. 24
0
        internal static void BuildVariantDropFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef variantDropFunction)
        {
            NIType variantType = signature.GetGenericParameters().First();

            Tuple <NIType, int>[] droppableFields = variantType.GetFields()
                                                    .Select((field, i) => new Tuple <NIType, int>(field, i))
                                                    .Where(field => field.Item1.GetDataType().TypeHasDropTrait()).ToArray();
            LLVMBasicBlockRef entryBlock = variantDropFunction.AppendBasicBlock("entry");

            Tuple <LLVMBasicBlockRef, int>[] dropBlocks = droppableFields.Select(field => new Tuple <LLVMBasicBlockRef, int>(variantDropFunction.AppendBasicBlock($"drop{field.Item1.GetName()}"), field.Item2)).ToArray();
            LLVMBasicBlockRef exitBlock = variantDropFunction.AppendBasicBlock("exit");

            var builder = moduleContext.LLVMContext.CreateIRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);
            LLVMValueRef variantPtr     = variantDropFunction.GetParam(0u),
                         variantTagPtr  = builder.CreateStructGEP(variantPtr, 0u, "variantTagPtr"),
                         variantDataPtr = builder.CreateStructGEP(variantPtr, 1u, "variantDataPtr"),
                         variantTag     = builder.CreateLoad(variantTagPtr, "variantTag"),
                         tagSwitch      = builder.CreateSwitch(variantTag, exitBlock, (uint)dropBlocks.Length);

            foreach (var pair in dropBlocks)
            {
                tagSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue((byte)pair.Item2), pair.Item1);
            }

            for (int i = 0; i < droppableFields.Length; ++i)
            {
                builder.PositionBuilderAtEnd(dropBlocks[i].Item1);
                NIType       fieldType       = droppableFields[i].Item1.GetDataType();
                LLVMTypeRef  fieldLLVMType   = moduleContext.LLVMContext.AsLLVMType(fieldType);
                LLVMValueRef bitCastFieldPtr = builder.CreateBitCast(variantDataPtr, LLVMTypeRef.PointerType(fieldLLVMType, 0u), "bitCastFieldPtr");
                moduleContext.CreateDropCallIfDropFunctionExists(builder, fieldType, _ => bitCastFieldPtr);
                builder.CreateBr(exitBlock);
            }

            builder.PositionBuilderAtEnd(exitBlock);
            builder.CreateRetVoid();
        }
        private LLVMValueRef BuildPollFunction()
        {
            LLVMValueRef      pollFunction = Module.AddFunction(FunctionNames.GetPollFunctionName(_functionName), PollFunctionType(SharedData.Context));
            LLVMBasicBlockRef entryBlock   = pollFunction.AppendBasicBlock("entry");
            var builder = SharedData.Context.CreateIRBuilder();

            var outerFunctionCompilerState = new OuterFunctionCompilerState(pollFunction, builder);

            CurrentState = outerFunctionCompilerState;
            builder.PositionBuilderAtEnd(entryBlock);
            LLVMValueRef stateVoidPtr = pollFunction.GetParam(0u),
                         statePtr     = builder.CreateBitCast(stateVoidPtr, LLVMTypeRef.PointerType(SharedData.AllocationSet.StateType, 0u), "statePtr");

            outerFunctionCompilerState.StateMalloc = statePtr;

            // store the caller waker in the state
            // TODO: create constants for these positions
            LLVMValueRef waker = builder.BuildStructValue(
                SharedData.Context.WakerType(),
                new LLVMValueRef[] { pollFunction.GetParam(1u), pollFunction.GetParam(2u) },
                "callerWaker");

            builder.CreateStore(waker, builder.CreateStructGEP(statePtr, 1u, "callerWakerPtr"));

            // set initial fire counts
            foreach (AsyncStateGroupData groupData in AsyncStateGroups.Values)
            {
                groupData.CreateFireCountReset(builder);
            }

            // schedule initial group(s)
            CreateScheduleCallsForAsyncStateGroups(
                builder,
                statePtr,
                AsyncStateGroups.Keys.Where(group => !group.Predecessors.Any()));

            builder.CreateRetVoid();
            return(pollFunction);
        }
Esempio n. 26
0
        private static LLVMValueRef CreateVectorGrowFunction(FunctionModuleContext moduleContext, string functionName, NIType elementType)
        {
            LLVMTypeRef elementLLVMType        = moduleContext.LLVMContext.AsLLVMType(elementType);
            LLVMTypeRef vectorGrowFunctionType = LLVMTypeRef.FunctionType(
                moduleContext.LLVMContext.VoidType,
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(moduleContext.LLVMContext.CreateLLVMVectorType(elementLLVMType), 0u),
            },
                false);

            LLVMValueRef      vectorGrowFunction = moduleContext.Module.AddFunction(functionName, vectorGrowFunctionType);
            LLVMBasicBlockRef entryBlock         = vectorGrowFunction.AppendBasicBlock("entry");
            var builder = moduleContext.LLVMContext.CreateIRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);
            LLVMValueRef vectorPtr         = vectorGrowFunction.GetParam(0u),
                         vector            = builder.CreateLoad(vectorPtr, "vector"),
                         oldAllocationPtr  = builder.CreateExtractValue(vector, 0u, "oldAllocationPtr"),
                         oldVectorCapacity = builder.CreateExtractValue(vector, 2u, "oldVectorCapacity"),
            // TODO: ideally handle integer overflow; also there are ways this could be smarter
                         newVectorCapacity = builder.CreateMul(oldVectorCapacity, moduleContext.LLVMContext.AsLLVMValue(2), "newVectorCapacity"),
            // TODO: handle the case where the allocation fails
                         newAllocationPtr        = moduleContext.CreateArrayMalloc(builder, elementLLVMType, newVectorCapacity, "newAllocationPtr"),
                         oldVectorCapacityExtend = builder.CreateSExt(oldVectorCapacity, moduleContext.LLVMContext.Int64Type, "oldVectorCapacityExtend"),
                         bytesToCopy             = builder.CreateMul(oldVectorCapacityExtend, elementLLVMType.SizeOf(), "bytesToCopy");

            moduleContext.CreateCallToCopyMemory(builder, newAllocationPtr, oldAllocationPtr, bytesToCopy);
            LLVMValueRef newVector0 = builder.CreateInsertValue(vector, newAllocationPtr, 0u, "newVector0"),
                         newVector  = builder.CreateInsertValue(newVector0, newVectorCapacity, 2u, "newVector");

            builder.CreateStore(newVector, vectorPtr);
            builder.CreateFree(oldAllocationPtr);
            builder.CreateRetVoid();
            return(vectorGrowFunction);
        }
Esempio n. 27
0
        public LLVMValueRef EmitMethodHeader(string pName, Syntax.MethodSyntax pMethod, out string pNewName)
        {
            //Get method return type
            LLVMTypeRef ret;

            if (pMethod.ReturnValues.Count == 0)
            {
                ret = LLVMTypeRef.VoidType();
            }
            else if (pMethod.ReturnValues.Count == 1)
            {
                ret = SmallTypeCache.GetLLVMType(pMethod.Type, this);
            }
            else
            {
                LLVMTypeRef[] types = new LLVMTypeRef[pMethod.ReturnValues.Count];
                for (int i = 0; i < types.Length; i++)
                {
                    types[i] = SmallTypeCache.GetLLVMType(pMethod.ReturnValues[i].Type, this);
                }
                ret = LLVM.StructType(types, false);
                Cache.SetLLVMType(pMethod.Type.Name, ret);
            }

            //If we are emitting a struct method we need to add "self" as a parameter
            SmallType[]   originalTypes = new SmallType[pMethod.Parameters.Count];
            LLVMTypeRef[] parmTypes     = null;
            int           start         = 0;

            if (CurrentStruct != null)
            {
                parmTypes    = new LLVMTypeRef[pMethod.Parameters.Count + 1];
                parmTypes[0] = LLVMTypeRef.PointerType(SmallTypeCache.GetLLVMType(CurrentStruct, this), 0);
                start        = 1;
            }
            else
            {
                parmTypes = new LLVMTypeRef[pMethod.Parameters.Count];
            }

            //Get parameter types
            for (int i = 0; i < pMethod.Parameters.Count; i++)
            {
                var parmType = pMethod.Parameters[i].Type;
                if (parmType.IsGenericParameter)
                {
                    originalTypes[i] = TypeMappings[parmType.Name];
                }
                else
                {
                    originalTypes[i] = parmType;
                }

                //For calling external methods with strings, we only want to pass the character array
                if (pMethod.External && parmType == SmallTypeCache.String)
                {
                    parmType = parmType.GetElementType();
                }

                parmTypes[start + i] = SmallTypeCache.GetLLVMType(parmType, this);
                if (pMethod.Parameters[i].Type.IsStruct || pMethod.Parameters[i].Type.IsArray)
                {
                    parmTypes[start + i] = LLVMTypeRef.PointerType(parmTypes[start + i], 0);
                }
            }

            var result = Cache.FindMethod(out MethodDefinition pDefinition, null, CurrentStruct, pName, originalTypes);

            Debug.Assert(result == Compiler.FindResult.Found);
            pNewName = pDefinition.MangledName;

            //Method header
            var func = LLVM.GetNamedFunction(CurrentModule, pNewName);

            if (func.Pointer == IntPtr.Zero)
            {
                func = LLVM.AddFunction(CurrentModule, pNewName, LLVM.FunctionType(ret, parmTypes, false));
                LLVM.SetLinkage(func, LLVMLinkage.LLVMExternalLinkage);
            }

            if (pMethod.External)
            {
                //Create attribute so we can find it later when executing
                var attribute = LLVM.CreateStringAttribute(_context, "external", 8, pMethod.Annotation.Value, (uint)pMethod.Annotation.Value.Length);
                LLVM.AddAttributeAtIndex(func, LLVMAttributeIndex.LLVMAttributeFunctionIndex, attribute);
            }

            return(func);
        }
Esempio n. 28
0
        bool ICodeGenElementVisitor <bool> .VisitBuildVariant(BuildVariant buildVariant)
        {
            LLVMValueRef variantAddress        = _codeGenValues[buildVariant.VariantAddressIndex],
                         variantTagFieldPtr    = Builder.CreateStructGEP(variantAddress, 0u, "variantTagFieldPtr"),
                         variantDataFieldPtr   = Builder.CreateStructGEP(variantAddress, 1u, "variantDataFieldPtr"),
                         inputValue            = _codeGenValues[buildVariant.FieldValueIndex],
                         bitCastAllocaFieldPtr = Builder.CreateBitCast(variantDataFieldPtr, LLVMTypeRef.PointerType(inputValue.TypeOf(), 0u), "bitCastAllocaFieldPtr");

            Builder.CreateStore(Context.AsLLVMValue((byte)buildVariant.FieldIndex), variantTagFieldPtr);
            Builder.CreateStore(inputValue, bitCastAllocaFieldPtr);
            return(true);
        }
Esempio n. 29
0
        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();
            }
        }
        internal static void CreateSliceIndexFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef sliceIndexFunction)
        {
            NIType      elementType          = signature.GetGenericParameters().First();
            LLVMTypeRef elementPtrOptionType = moduleContext.LLVMContext.CreateLLVMOptionType(LLVMTypeRef.PointerType(moduleContext.LLVMContext.AsLLVMType(elementType), 0u));

            LLVMBasicBlockRef entryBlock        = sliceIndexFunction.AppendBasicBlock("entry"),
                              validIndexBlock   = sliceIndexFunction.AppendBasicBlock("validIndex"),
                              invalidIndexBlock = sliceIndexFunction.AppendBasicBlock("invalidIndex");
            var builder = moduleContext.LLVMContext.CreateIRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);
            LLVMValueRef indexPtr    = sliceIndexFunction.GetParam(0u),
                         index       = builder.CreateLoad(indexPtr, "index"),
                         sliceRef    = sliceIndexFunction.GetParam(1u),
                         sliceLength = builder.CreateExtractValue(sliceRef, 1u, "sliceLength"),
                         indexLessThanSliceLength = builder.CreateICmp(LLVMIntPredicate.LLVMIntSLT, index, sliceLength, "indexLTSliceLength"),
                         indexNonNegative         = builder.CreateICmp(LLVMIntPredicate.LLVMIntSGE, index, moduleContext.LLVMContext.AsLLVMValue(0), "indexNonNegative"),
                         indexInBounds            = builder.CreateAnd(indexLessThanSliceLength, indexNonNegative, "indexInBounds"),
                         elementPtrOptionPtr      = sliceIndexFunction.GetParam(2u);

            builder.CreateCondBr(indexInBounds, validIndexBlock, invalidIndexBlock);

            builder.PositionBuilderAtEnd(validIndexBlock);
            LLVMValueRef sliceBufferPtr = builder.CreateExtractValue(sliceRef, 0u, "sliceBufferPtr"),
                         elementPtr     = builder.CreateGEP(sliceBufferPtr, new LLVMValueRef[] { index }, "elementPtr"),
                         someElementPtr = moduleContext.LLVMContext.BuildOptionValue(builder, elementPtrOptionType, elementPtr);

            builder.CreateStore(someElementPtr, elementPtrOptionPtr);
            builder.CreateRetVoid();

            builder.PositionBuilderAtEnd(invalidIndexBlock);
            LLVMValueRef noneElementPtr = moduleContext.LLVMContext.BuildOptionValue(builder, elementPtrOptionType, null);

            builder.CreateStore(noneElementPtr, elementPtrOptionPtr);
            builder.CreateRetVoid();
        }