Example #1
0
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 &parameters = fType->parameters();

    for (int i = parameters.size() - 1; i >= 0; --i)
    {
	const Param &param = 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 &parameters = type->parameters();

    vector<FunctionArgPtr> inputs;
    vector<FunctionArgPtr> outputs;
    for (int i = parameters.size() - 1; i >= 0; --i)
    {
	const Param &param = 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);
    }
}
Example #3
0
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 &parameters = 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();
}