示例#1
0
        public void Insert(Function function)
        {
            FunctionGroupName gname = new FunctionGroupName(function.GetFunctionType(), function.IsStatic());

            gname.SetFunction(function);
            functions.Add(gname);
        }
示例#2
0
        private void PrepareReturning(AstNode where, Function function, LexicalScope scope)
        {
            // Get the definition node and check for generator.
            FunctionDefinition defNode = function.DefinitionNode;
            bool isGenerator = false;
            if(defNode != null)
                isGenerator = defNode.IsGenerator;

            // Use standard return.
            if(function.GetExceptionContext() == null && !isGenerator)
                return;

            // Create the return block.
            BasicBlock returnBlock = new BasicBlock(function);
            returnBlock.SetName("retBlock");
            function.ReturnBlock = returnBlock;

            // Create the return value local.
            FunctionType functionType = function.GetFunctionType();
            IChelaType retType = functionType.GetReturnType();
            if(retType != ChelaType.GetVoidType() && !isGenerator)
                function.ReturnValueVar = new LocalVariable(GenSym() + "_retval", scope, retType);

            // Create the is returning flag.
            function.ReturningVar = new LocalVariable(GenSym() + "_isret", scope, ChelaType.GetBoolType(), isGenerator);
            function.ReturningVar.Type = LocalType.Return;

            // Create the field for generators.
            if(isGenerator)
            {
                FieldVariable returningField = new FieldVariable("returning", MemberFlags.Private,
                    ChelaType.GetBoolType(), defNode.GeneratorClass);
                defNode.GeneratorClass.AddField(returningField);
                function.ReturningVar.ActualVariable = returningField;
            }

            // Initializer the returning flag to false.
            builder.CreateLoadBool(false);
            PerformAssignment(where, function.ReturningVar);
        }
示例#3
0
        private void FinishReturn(AstNode node, Function function)
        {
            // Get the return block.
            BasicBlock returnBlock = function.ReturnBlock;

            // Get the definition node and check for generator.
            FunctionDefinition defNode = function.DefinitionNode;
            bool isGenerator = false;
            if(defNode != null)
                isGenerator = defNode.IsGenerator;

            // Add implicit void return.
            FunctionType functionType = function.GetFunctionType();
            IChelaType retType = functionType.GetReturnType();
            IChelaType voidType = ChelaType.GetVoidType();
            if(!builder.IsLastTerminator())
            {
                if(retType == voidType || isGenerator)
                {
                    if(returnBlock != null)
                    {
                        builder.CreateJmp(returnBlock);
                    }
                    else if(isGenerator)
                    {
                        builder.CreateLoadBool(false);
                        builder.CreateRet();
                    }
                    else
                    {
                        builder.CreateRetVoid();
                    }
                }
                else
                {
                    //function.Dump();
                    Error(node, "not all of the function code paths returns something.");
                }
            }

            // Build the return block.
            if(returnBlock != null)
            {
                builder.SetBlock(returnBlock);

                // Perform return.
                if(isGenerator)
                {
                    // Set the disposed state.
                    builder.CreateLoadArg(0);
                    builder.CreateLoadInt32(1);
                    builder.CreateStoreField(defNode.GeneratorState);

                    // Return false in MoveNext.
                    builder.CreateLoadBool(false);
                    builder.CreateRet();
                }
                else if(retType == voidType)
                {
                    builder.CreateRetVoid();
                }
                else
                {
                    builder.CreateLoadLocal(function.ReturnValueVar);
                    builder.CreateRet();
                }
            }
        }
示例#4
0
 public void Insert(Function function)
 {
     FunctionGroupName gname = new FunctionGroupName(function.GetFunctionType(), function.IsStatic());
     gname.SetFunction(function);
     functions.Add(gname);
 }
示例#5
0
        private void CreateKernelEntryPoint(AstNode where, Function function)
        {
            // Only create once
            if(function.EntryPoint != null)
                return;

            // Get the function type.
            FunctionType functionType = function.GetFunctionType();

            // The return type must be void.
            if(functionType.GetReturnType() != ChelaType.GetVoidType())
                return;

            // Check the parameters for input and output streams, and not references.
            bool inputStream = false;
            bool outputStream = false;
            for(int i = 0; i < functionType.GetArgumentCount(); ++i)
            {
                IChelaType argType = functionType.GetArgument(i);

                // Streams are references.
                if(!argType.IsReference())
                    continue;

                // Cast the argument.
                ReferenceType argRef = (ReferenceType)argType;

                // Only stream and array references are supported in kernel entry points.
                if(!argRef.IsStreamReference())
                {
                    argType = argRef.GetReferencedType();
                    if(argType.IsArray())
                        continue;
                    return;
                }

                // Check the stream flow.
                ReferenceFlow flow = argRef.GetReferenceFlow();
                if(flow == ReferenceFlow.In || flow == ReferenceFlow.InOut)
                    inputStream = true;
                if(flow == ReferenceFlow.Out || flow == ReferenceFlow.InOut)
                    outputStream = true;

                // Don't stop the loop to check for the non-stream references.
            }

            // Both types of streams must be present.
            if(!inputStream || !outputStream)
                return;

            // Now create the entry point function type.
            List<IChelaType> arguments = new List<IChelaType> ();
            for(int i = 0; i < functionType.GetArgumentCount(); ++i)
            {
                IChelaType argType = functionType.GetArgument(i);

                // Select the adecuate holder.
                Class holder = null;
                if(!argType.IsReference())
                {
                    // Use uniform holder for non-stream and non-array arguments.
                    holder = currentModule.GetUniformHolderClass();
                }
                else
                {
                    // De-Reference the argument type.
                    ReferenceType refType = (ReferenceType)argType;
                    argType = refType.GetReferencedType();

                    // Get the array dimensions.
                    int dimensions = 0;
                    if(argType.IsArray())
                    {
                        ArrayType arrayType = (ArrayType)argType;
                        argType = arrayType.GetValueType();
                        dimensions = arrayType.GetDimensions();
                    }
                    else
                    {
                        // TODO: Read the dimensions from the reference type.
                    }

                    // Select the stream holder according to the dimensions.
                    switch(dimensions)
                    {
                    case 0:
                        holder = currentModule.GetStreamHolderClass();
                        break;
                    case 1:
                        holder = currentModule.GetStreamHolder1DClass();
                        break;
                    case 2:
                        holder = currentModule.GetStreamHolder2DClass();
                        break;
                    case 3:
                        holder = currentModule.GetStreamHolder3DClass();
                        break;
                    default:
                        Error(where, "unsupported array with more than 3 dimensions in kernels.");
                        break;
                    }
                }

                // Create an stream holder instance.
                GenericInstance instanceData = new GenericInstance(holder.GetGenericPrototype(),
                    new IChelaType[]{argType});
                IChelaType holderType = holder.InstanceGeneric(instanceData, currentModule);

                // Store the stream holder type.
                if(holderType.IsPassedByReference())
                    holderType = ReferenceType.Create(holderType);
                arguments.Add(holderType);
            }

            // Create the kernel binder type.
            IChelaType computeBindingType = ReferenceType.Create(currentModule.GetComputeBindingDelegate());
            FunctionType kernelBinderType = FunctionType.Create(computeBindingType, arguments);

            // Create the kernel entry point.
            function.EntryPoint = new KernelEntryPoint(function, kernelBinderType);
        }
示例#6
0
        private void CheckMainCandidate(AstNode node, Function main)
        {
            // Ignore the main type if the module is not executable.
            if(currentModule.GetModuleType() != ModuleType.Executable)
                return;

            // Get the function type.
            FunctionType type = main.GetFunctionType();

            // Check the return type.
            IChelaType returnType = type.GetReturnType();
            if(returnType != ChelaType.GetVoidType() &&
               returnType != ChelaType.GetIntType())
                return;

            // Check the argument count.
            if(type.GetArgumentCount() > 1)
                return;

            // Check the argument.
            if(type.GetArgumentCount() == 1)
            {
                IChelaType strArrayType = ReferenceType.Create(ArrayType.Create(currentModule.TypeMap(ChelaType.GetStringType())));
                if(strArrayType != type.GetArgument(0))
                   return;
            }

            // Make usure it could be.
            string fullName = main.GetFullName();
            string mainName = currentModule.GetMainName();
            if(mainName != null && fullName != mainName)
                return;

            // This is a main candidate.
            Function oldMain = currentModule.GetMainFunction();
            if(oldMain != null && oldMain != main)
                Error(node, "multiple main functions defined");

            // This is the main.
            currentModule.SetMainFunction(main);
        }