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(); }
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) { 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; }