FunctionCallPtr Interpreter::newFunctionCall (const std::string &functionName) { Lock lock (_data->mutex); // // Calling a CTL function with variable-size array arguments // from C++ is not supported. // const SymbolInfoPtr info = symtab().lookupSymbol (functionName); if (!info) THROW (ArgExc, "Cannot find CTL function " << functionName << "."); if (!info->isFunction()) THROW (TypeExc, "CTL object " << functionName << " is not a function " "(it is of type " << info->type()->asString() << ")."); const FunctionTypePtr fType = info->type(); const ParamVector ¶meters = fType->parameters(); for (int i = parameters.size() - 1; i >= 0; --i) { const Param ¶m = parameters[i]; ArrayTypePtr aType = param.type.cast<ArrayType>(); if(aType) { SizeVector sizes; aType->sizes (sizes); for (int j = 0; j < sizes.size(); j++) { if (sizes[j] == 0) THROW (ArgExc, "CTL function " << functionName << " " "has a variable-size array " "argument, " << param.name << ", and can " "only be called by another CTL function."); } } } return newFunctionCallInternal (info, functionName); }
SimdFunctionCall::SimdFunctionCall (SimdInterpreter &interpreter, const string &name, FunctionTypePtr type, SimdInstAddrPtr addr, SymbolTable &symbols) : FunctionCall (name), _xcontext (interpreter), _entryPoint (addr->inst()), _symbols(symbols) { { SimdReg *returnReg = new SimdReg (type->returnVarying(), type->returnType()->alignedObjectSize()); _xcontext.stack().push (returnReg, TAKE_OWNERSHIP); setReturnValue (new SimdFunctionArg ("", this, type->returnType(), type->returnVarying(), returnReg)); } const ParamVector ¶meters = type->parameters(); vector<FunctionArgPtr> inputs; vector<FunctionArgPtr> outputs; for (int i = parameters.size() - 1; i >= 0; --i) { const Param ¶m = parameters[i]; SimdReg *paramReg = new SimdReg (param.varying, param.type->alignedObjectSize()); _xcontext.stack().push (paramReg, TAKE_OWNERSHIP); FunctionArgPtr arg = new SimdFunctionArg (param.name, this, param.type, param.varying, paramReg); if (param.isWritable()) outputs.push_back(arg); else inputs.push_back(arg); } int count = 0; for(vector<FunctionArgPtr>::reverse_iterator it = inputs.rbegin(); it != inputs.rend(); ++it) { setInputArg (count++, *it); } count = 0; for(vector<FunctionArgPtr>::reverse_iterator it = outputs.rbegin(); it != outputs.rend(); ++it) { setOutputArg (count++, *it); } }
void CallNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo) { // // Compute the type of a function call. This is the same type // as the function's return type, provided the call is valid. // // // Verify that what we are trying to call is actually a function. // if (!function) return; function->computeType (lcontext, initInfo); if (!function->type) return; FunctionTypePtr functionType = function->type.cast <FunctionType>(); if (!functionType) { MESSAGE_LE (lcontext, ERR_NON_FUNC, function->lineNumber, "Invalid function call to call non-function " "(" << function->name << " is of type " << function->type->asString() << ")."); return; } // // We shouldn't have more function call arguments than parameters. // const ParamVector ¶meters = functionType->parameters(); if (arguments.size() > parameters.size()) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_NUM, function->lineNumber, "Too many arguments in call to function " << function->name << "."); return; } // // Compare the types of the arguments to the call with // the types of the function's parameters. // for (int i = 0; i < (int)parameters.size(); ++i) { if (i < (int)arguments.size()) { // // We have a function call argument for parameter i. // arguments[i]->computeType (lcontext, initInfo); TypePtr argType = arguments[i]->type; if (!argType) return; DataTypePtr paramType = parameters[i].type; if (parameters[i].isWritable()) { // // output parameter -- argument must be an lvalue // of the same type as the parameter // if (!arguments[i]->isLvalue (initInfo)) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_LVAL, arguments[i]->lineNumber, "Argument " << i+1 << " in call to function " << function->name << " corresponds to an output " "parameter but it is not an lvalue."); return; } if (!paramType->isSameTypeAs (argType)) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_TYPE, arguments[i]->lineNumber, "Type of argument " << i+1 << " in call to " "function " << function->name << " is not the " "same as the type of the function's parameter " "(" << argType->asString() << " value " "for " << paramType->asString() << " parameter.)"); return; } } else { // // input parameter -- it must be possible to cast // the argument type to the parameter type // if (!paramType->canCastFrom (argType)) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_TYPE, arguments[i]->lineNumber, "Cannot convert the type of argument " << i+1 << " " "in call to function " << function->name << " " "to the type of the function's parameter " "(" << argType->asString() << " value " "for " << paramType->asString() << " parameter.)"); return; } } } else { // // We have no function call argument for parameter i. // The parameter must have a default value. // if (!parameters[i].defaultValue) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_NUM, function->lineNumber, "Not enough arguments in call to " "function " << function->name << "."); return; } } } // // If we get here, then the call is valid. // type = functionType->returnType(); }