Example #1
0
        public static Expression Convert(ConversionState state, ConversionResult expressionResult, MethodStruct methodStruct)
        {
            #region // result will be stored in a temporary value
            bool        complexIndexer;
            ComputeType receiverComputeType;
            if (methodStruct.Type is ARRAY_TYPE)
            {
                // result is array
                ComputeType.FromType(methodStruct.Type).TryGetValue(out receiverComputeType);
            }
            else
            {
                // result is scalar
                receiverComputeType = new ComputeType(ComputeScalarType.Single, 1);
            }
            Identifier receiverIdentifier = Identifier.For("ret");

            Expression[] indices = ConversionHelper.GetExpressionsFromIndexer(null, ref receiverComputeType, out complexIndexer);

            complexIndexer |= expressionResult.HasComplexIndexer;

            #endregion

            List <ConversionHelper.Argument> sortedArguments = ConversionHelper.ExtractArguments(state, false);
            List <ConversionHelper.Argument> scalarArguments = ConversionHelper.ExtractArguments(state, true);

            //ExpressionArgument receiverArgument;
            //ConversionHelper.ProcessReceiver(state, expressionResult, receiverIdentifier, receiverComputeType, indices, null, ref sortedArguments, complexIndexer, out receiverArgument);

            #region // add the temporary variable as a receiver
            ExpressionArgument receiverArgument = new ExpressionArgument(sortedArguments.Count, indices, null, -1);
            sortedArguments.Add(new ConversionHelper.Argument {
                Index     = receiverArgument.Index,
                Name      = receiverIdentifier.ToString(),
                Indexers  = receiverArgument.Indexers,
                IsRead    = false,
                IsWritten = true,
                IsCall    = receiverArgument.IsCall,
                CallRank  = receiverArgument.CallRank,
            });

            Identifier receiverDataIdentifier = Identifier.For("data" + receiverArgument.Index);
            if (!expressionResult.HasComplexIndexer)
            {
                // allocate receiver (1D array with size 1 for scalar result, matrix (vector) in other cases)
                ExpressionList ctorExpr = new ExpressionList();
                for (int index = 0; index < receiverComputeType.Rank; index++)
                {
                    ctorExpr.Add(NodeHelper.GetConstantIndexerForExpression(expressionResult.SizeIdentifier, index));
                }
                state.Constructor.Body.Statements.Add(
                    new AssignmentStatement {
                    Target = new AddressDereference {
                        Address = receiverDataIdentifier,
                        Type    = STANDARD.Data,
                    },
                    Source = new Construct {
                        Constructor = new MemberBinding {
                            BoundMember = STANDARD.Data.GetConstructor(SystemTypes.Array),
                        },
                        Operands = new ExpressionList(
                            new ConstructArray {
                            ElementType = expressionResult.Type.ScalarType.TypeNode,
                            Rank        = (methodStruct.Type is ARRAY_TYPE) ? receiverComputeType.Rank : 1,
                            Operands    = (methodStruct.Type is ARRAY_TYPE) ? ctorExpr : new ExpressionList(Literal.Int32One),
                        }
                            ),
                    }
                }
                    );
            }
            else
            {
                state.Constructor.Body.Statements.Add(new Block {
                    Statements = ConversionHelper.GenerateIndexedSize(expressionResult, receiverComputeType, receiverDataIdentifier, state.GetNextTempSizeIdentifier())
                });
            }
            #endregion

            #region // generate kernel
            ConversionResult?result = GenereteKernel(state, expressionResult, Identifier.For("buffer" + receiverArgument.Index.ToString()), methodStruct);
            ConversionResult finalConversionResult;
            if (result.HasValue)
            {
                finalConversionResult = result.Value;
            }
            else
            {
                return(null);
            }
            #endregion

            #region // generate delegates
            DelegateNode getOpenCLTimeDelegateType;
            DelegateNode startOpenCLDelegateType;
            ConversionHelper.GenerateOpenCLDelegates(state, out getOpenCLTimeDelegateType, out startOpenCLDelegateType);
            #endregion

            #region // generate get time method
            ConversionHelper.GenerateTimeMethod(state);
            #endregion

            #region // generate the codelets
            Identifier codeletsIdentifier;
            ConversionHelper.GenerateCodelets(state, getOpenCLTimeDelegateType, startOpenCLDelegateType, out codeletsIdentifier);
            #endregion

            #region // process all arguments - add them to parameters and data uses
            ExpressionList  ctorArgs   = new ExpressionList();
            ExpressionList  callArgs   = new ExpressionList();
            ParameterList   callParams = new ParameterList();
            List <TypeNode> typeList   = new List <TypeNode>();

            Identifier dataUsesIdentifier;
            ConversionHelper.ProcessArguments(state, sortedArguments, scalarArguments, complexIndexer, startOpenCLDelegateType, out dataUsesIdentifier, ref callParams, ref callArgs, ref state.Constructor.Parameters, ref ctorArgs, ref typeList);

            #endregion

            ConversionHelper.GenerateSubmitCodelet(state, codeletsIdentifier, dataUsesIdentifier);
            ConversionHelper.FinishOperation(state, finalConversionResult);

            Class actualOperationClass = CONTEXT._operationRegistry.RegisterOperation(finalConversionResult.CompleteExpression, state.Class);

            #region // create method 'call'
            Identifier callIdentifier = Identifier.For("call");
            Method     callMethod     = actualOperationClass.GetMethod(callIdentifier, typeList.ToArray());
            Expression returnExp;
            if (methodStruct.Type is ARRAY_TYPE)
            {
                returnExp = receiverIdentifier;
            }
            else
            {
                returnExp = new BinaryExpression {
                    NodeType = NodeType.Castclass,
                    Operand2 = new MemberBinding {
                        BoundMember = expressionResult.Type.ScalarType.TypeNode.GetArrayType(1)
                    },
                    Operand1 = new MethodCall {
                        Callee = new MemberBinding {
                            TargetObject = receiverIdentifier,
                            BoundMember  = STANDARD.Data.GetMethod(Identifier.For("GetHostArray")),
                        },
                    }
                };
            }
            if (methodStruct.Type is ARRAY_TYPE)
            {
            }
            else
            {
                returnExp = NodeHelper.GetConstantIndexerForExpression(returnExp, 0);
                if (methodStruct.Type is BOOLEAN_TYPE)
                {
                    // if it was a boolean operation invert the value (1 is false in OpenCL kernel)
                    returnExp = new BinaryExpression {
                        NodeType = NodeType.Eq,
                        Operand1 = returnExp,
                        Operand2 = Literal.Int32Zero
                    };
                }
            }
            if (callMethod == null)
            {
                actualOperationClass.Members.Add(new Method {
                    DeclaringType = state.Class,
                    Flags         = MethodFlags.Static,
                    ReturnType    = (methodStruct.Type is ARRAY_TYPE) ? STANDARD.Data : methodStruct.Type.convert() as TypeNode /*receiverComputeType.ScalarType.TypeNode*/,
                    Parameters    = callParams,
                    Name          = callIdentifier,
                    Body          = new Block {
                        Statements = new StatementList(
                            new VariableDeclaration {
                            Name = receiverIdentifier,
                            Type = STANDARD.Data,
                        },
                            new ExpressionStatement(new Construct {
                            Constructor = new MemberBinding {
                                BoundMember = actualOperationClass.GetConstructors()[0],
                            },
                            Operands = ctorArgs,
                        }),

                            new Return(returnExp)
                            )
                    }
                });
            }
            #endregion

            #region // return call to 'call'
            return(new MethodCall {
                Operands = callArgs,
                Callee = new MemberBinding(null, actualOperationClass.GetMethod(callIdentifier, typeList.ToArray())),
                Type = expressionResult.Type.ScalarType.TypeNode,
            });

            #endregion
        }