private AstNode VectorConstruction(CallExpression node) { // Begin the node. builder.BeginNode(node); // Retrieve the types. IChelaType targetType = node.GetNodeType(); IChelaType coercionType = node.GetCoercionType(); // Push the arguments. AstNode argExpr = node.GetArguments(); while(argExpr != null) { // Visit the argument. argExpr.Accept(this); // Coerce it. IChelaType argExprType = argExpr.GetNodeType(); if(argExprType != coercionType) { // De-ref and de-const IChelaType argCoercionType = argExprType; if(argCoercionType.IsReference()) argCoercionType = DeReferenceType(argCoercionType); if(argCoercionType.IsConstant()) argCoercionType = DeConstType(argCoercionType); if(argCoercionType.IsPrimitive()) { // Use normal casting. Cast(node, argExpr.GetNodeValue(), argExprType, coercionType); } else { // Coercion to a vector with the same size. VectorType argVector = (VectorType)argCoercionType; argCoercionType = VectorType.Create(coercionType, argVector.GetNumComponents()); if(argCoercionType != argExprType) Cast(node, argExpr.GetNodeValue(), argExprType, argCoercionType); } } // Process the next argument. argExpr = argExpr.GetNext(); } // Create the vector. if(targetType.IsVector()) builder.CreateNewVector(targetType); else builder.CreateNewMatrix(targetType); return builder.EndNode(); }
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(); }