void ImplementByRefICallableCall(
Method call,
InternalCallableType type,
ClassDefinition node,
CallableSignature signature,
int byRefCount)
{
MethodInvocationExpression mie = CreateInvokeInvocation(type);
IParameter[] parameters = signature.Parameters;
ReferenceExpression args = CodeBuilder.CreateReference(call.Parameters[0]);
InternalLocal[] temporaries = new InternalLocal[byRefCount];
int byRefIndex = 0;
for (int i=0; i<parameters.Length; ++i)
{
SlicingExpression slice = CodeBuilder.CreateSlicing(args.CloneNode(), i);
IParameter parameter = parameters[i];
if (parameter.IsByRef)
{
IType tempType = parameter.Type;
if (tempType.IsByRef)
{
tempType = tempType.GetElementType();
}
temporaries[byRefIndex] = CodeBuilder.DeclareLocal(call,
"__temp_" + parameter.Name,
tempType);
call.Body.Add(
CodeBuilder.CreateAssignment(
CodeBuilder.CreateReference(temporaries[byRefIndex]),
CodeBuilder.CreateCast(
tempType,
slice)));
mie.Arguments.Add(
CodeBuilder.CreateReference(
temporaries[byRefIndex]));
++byRefIndex;
}
else
{
mie.Arguments.Add(slice);
}
}
if (TypeSystemServices.VoidType == signature.ReturnType)
{
call.Body.Add(mie);
PropagateByRefParameterChanges(call, parameters, temporaries);
}
else
{
InternalLocal invokeReturnValue = CodeBuilder.DeclareLocal(call,
"__returnValue", signature.ReturnType);
call.Body.Add(
CodeBuilder.CreateAssignment(
CodeBuilder.CreateReference(invokeReturnValue),
mie));
PropagateByRefParameterChanges(call, parameters, temporaries);
call.Body.Add(
new ReturnStatement(
CodeBuilder.CreateReference(invokeReturnValue)));
}
}