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