Пример #1
0
        public override AstNode Visit(CallExpression node)
        {
            if(node.IsVectorConstruction())
                return VectorConstruction(node);

            // Begin the node.
            builder.BeginNode(node);

            // Get the functional expression.
            Expression functionalExpression = node.GetFunction();

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

            // Visit the functional expression.
            functionalExpression.Accept(this);

            // Check if suppressing virtual calls.
            FunctionGroupSelector selector = functionalExpression.GetNodeValue() as FunctionGroupSelector;
            bool implicitThis = node.HasImplicitArgument();
            bool suppressVirtual = false;
            Function function = node.GetSelectedFunction();
            if(selector != null)
            {
                suppressVirtual = selector.SuppressVirtual;
                implicitThis = implicitThis || (selector.ImplicitThis && !function.IsStatic());
            }

            // Cast the function expression.
            IChelaType exprType = functionalExpression.GetNodeType();
            IChelaType functionCoercion = exprType;

            // Load variables.
            if(functionCoercion.IsReference())
               functionCoercion = DeReferenceType(exprType);
            if(exprType != functionCoercion)
                Cast(node, functionalExpression.GetNodeValue(), exprType, functionCoercion);

            // Push the arguments.
            AstNode argExpr = node.GetArguments();
            int index = implicitThis ? 1 : 0;
            while(argExpr != null)
            {
                // Visit the argument.
                argExpr.Accept(this);

                // Don't cast reference argument
                Variable argVariable = argExpr.GetNodeValue() as Variable;
                bool refArg = argVariable != null && argVariable.IsTemporalReferencedSlot();

                // Coerce it.
                IChelaType argExprType = argExpr.GetNodeType();
                IChelaType argType = functionType.GetArgument(index++);
                if(argType != argExprType && !refArg)
                    Cast(node, argExpr.GetNodeValue(), argExprType, argType);

                // Push the next argument.
                argExpr = argExpr.GetNext();
            }

            // Store the number of arguments.
            int numargs = index;

            // Perform a call if the function is known, otherwise an indirect call.
            if(function != null)
            {
                // Use different opcode for virtual calls.
                if(function.IsKernelEntryPoint())
                {
                    KernelEntryPoint entryPoint = (KernelEntryPoint)function;
                    builder.CreateBindKernel(DeReferenceType(node.GetNodeType()), entryPoint.Kernel);
                }
                else if(function.IsConstructor())
                    builder.CreateNewStruct(node.GetNodeType(), function, (uint)(numargs-1));
                else if(!function.IsVirtualCallable() || function.GetParentScope().IsStructure() || suppressVirtual)
                    builder.CreateCall(function, (uint)numargs);
                else
                    builder.CreateCallVirtual(function, (uint)numargs);
            }
            else
            {
                // Call the object.
                builder.CreateCallIndirect((uint)numargs);
            }

            return builder.EndNode();
        }
Пример #2
0
        public override AstNode Visit(CallExpression node)
        {
            Function function = ProcessCall(node, node.GetFunction(), node.GetArguments());

            // Get the function type.
            IChelaType functionType = node.GetFunction().GetNodeType();

            // Perform additional checks when the function is known.
            if(function != null)
            {
                // Set the selected function.
                node.SelectFunction(function);

                // Set the presence of a 'this' reference.
                node.SetImplicitArgument(!function.IsStatic());

                // Additional checks for methods.
                if(function.IsMethod())
                {
                    Method method = (Method)function;

                    // Get the virtual slot.
                    node.SetVSlot(method.GetVSlot());
                }
            }
            else if(functionType.IsMetaType())
            {
                // This can be a primitive cast, or a vector construction.
                IChelaType targetType = ExtractActualType(node.GetFunction(), functionType);
                if(targetType.IsPrimitive())
                {
                    // Primitive cast.
                    Error(node, "unimplemented primitive construction form.");
                }
                else if(targetType.IsVector() || targetType.IsMatrix())
                {
                    // Vector/Matrix construction.
                    IChelaType coercionType = null;
                    node.SetNodeType(targetType);

                    // Extract the number of components.
                    int typeComps = 0;
                    if(targetType.IsVector())
                    {
                        VectorType vectorType = (VectorType)targetType;
                        coercionType = vectorType.GetPrimitiveType();
                        typeComps = vectorType.GetNumComponents();
                    }
                    else
                    {
                        MatrixType matrixType = (MatrixType)targetType;
                        coercionType = matrixType.GetPrimitiveType();
                        typeComps = matrixType.GetNumColumns() * matrixType.GetNumRows();

                    }
                    node.SetCoercionType(coercionType);

                    node.SetVectorConstruction(true);

                    // Perform argument coercion.
                    int numcomponents = 0;
                    AstNode arg = node.GetArguments();
                    while(arg != null)
                    {
                        IChelaType argType = arg.GetNodeType();
                        if(argType != coercionType &&
                           Coerce(coercionType, argType) != coercionType)
                        {
                            // Deref and deconst the argument.
                            if(argType.IsReference())
                               argType = DeReferenceType(argType);
                            if(argType.IsConstant())
                                argType = DeConstType(argType);

                            // Check if its a vector
                            if(!argType.IsVector())
                                Error(arg, "invalid vector initialization argument: " + argType + " -> " + coercionType);

                            // Check the component compatibility.
                            VectorType argVector = (VectorType)argType;
                            IChelaType argComponent = argVector.GetPrimitiveType();
                            if(argComponent != coercionType &&
                               Coerce(coercionType, argComponent) != coercionType)
                                Error(arg, "incompatible vector components types: " +  argComponent + " -> " + coercionType);

                            // Add the components.
                            numcomponents += argVector.GetNumComponents();
                        }
                        else
                        {
                            // Add one component.
                            ++numcomponents;
                        }

                        // Check the next argument.
                        arg = arg.GetNext();
                    }

                    // Check the number of components is correct.
                    if(numcomponents != typeComps)
                        Error(node, "the number of components is incorrect.");
                }
            }

            return node;
        }