public void FunctionCallExpression(CParser.FunctionCallExpression FunctionCallExpression)
{
var Function = FunctionCallExpression.Function;
if (Function is CParser.IdentifierExpression)
{
var IdentifierExpression = Function as CParser.IdentifierExpression;
var FunctionName = IdentifierExpression.Identifier;
var ParametersExpressions = FunctionCallExpression.Parameters.Expressions;
// Special functions.
switch (FunctionName)
{
// Alloca Special Function.
case "alloca":
{
#if true
// alloca requires the stack to be empty after calling it?
var Stack = SafeILGenerator.StackSave();
var AllocaAddressLocal = SafeILGenerator.DeclareLocal(typeof(void*));
{
Traverse(ParametersExpressions);
SafeILGenerator.StackAlloc();
}
SafeILGenerator.StoreLocal(AllocaAddressLocal);
SafeILGenerator.StackRestore(Stack);
SafeILGenerator.LoadLocal(AllocaAddressLocal);
#else
var AllocaLocal = SafeILGenerator.DeclareLocal(typeof(void*), "AllocaLocal");
Traverse(FunctionCallExpression.Parameters.Expressions);
//SafeILGenerator.ConvertTo(typeof(void*));
SafeILGenerator.StackAlloc();
SafeILGenerator.ConvertTo(typeof(void*));
SafeILGenerator.StoreLocal(AllocaLocal);
SafeILGenerator.LoadLocal(AllocaLocal);
//throw(new NotImplementedException("Currently this does not work!"));
#endif
}
break;
// Normal plain function.
default:
{
var VariableReference = VariableScope.Find(IdentifierExpression.Identifier);
var FunctionReference = FunctionScope.Find(IdentifierExpression.Identifier);
if (VariableReference != null)
{
var CFunctionType = VariableReference.CType.GetSpecifiedCType<CFunctionType>();
var ReturnType = ConvertCTypeToType(CFunctionType.Return);
var ParameterTypes = CFunctionType.Parameters.Select(Item => ConvertCTypeToType(Item.CType)).ToArray();
Traverse(ParametersExpressions);
Traverse(IdentifierExpression);
SafeILGenerator.CallManagedFunction(CallingConventions.Standard, ReturnType, ParameterTypes, null);
}
else if (FunctionReference != null)
{
Type[] ParameterTypes;
if (FunctionReference.SafeMethodTypeInfo == null)
{
if (FunctionReference.MethodInfo.CallingConvention == CallingConventions.VarArgs)
{
ParameterTypes = FunctionCallExpression.Parameters.Expressions.Select(Expression => ConvertCTypeToType(Expression.GetCachedCType(this))).ToArray();
}
else
{
ParameterTypes = FunctionReference.MethodInfo.GetParameters().Select(Parameter => Parameter.ParameterType).ToArray();
}
}
else
{
ParameterTypes = FunctionReference.SafeMethodTypeInfo.Parameters;
}
if (ParameterTypes.Length != ParametersExpressions.Length)
{
throw (new Exception(String.Format(
"Function parameter count mismatch {0} != {1} calling function '{2}'",
ParameterTypes.Length, ParametersExpressions.Length, FunctionName
)));
}
ParameterTypes = ParameterTypes.Select(Item => GetRealType(Item)).ToArray();
for (int n = 0; n < ParametersExpressions.Length; n++)
{
var Expression = ParametersExpressions[n];
var ExpressionCType = Expression.GetCachedCType(this);
var ExpressionType = ConvertCTypeToType(ExpressionCType);
var ParameterType = GetRealType(ParameterTypes[n]);
Traverse(Expression);
// Expected a string. Convert it!
if (ParameterType == typeof(string))
{
if (ExpressionType == typeof(sbyte*))
{
SafeILGenerator.ConvertTo(typeof(sbyte*));
SafeILGenerator.Call((CLibUtils.PointerToStringDelegate)CLibUtils.GetStringFromPointer);
}
else
{
throw (new NotImplementedException(String.Format("Invalid string expression {0}", ExpressionType)));
}
}
else
{
SafeILGenerator.ConvertTo(ParameterType);
}
}
if (FunctionReference.SafeMethodTypeInfo == null && FunctionReference.MethodInfo.CallingConvention == CallingConventions.VarArgs)
{
//SafeILGenerator.LoadFunctionPointer(FunctionReference.MethodInfo, IsVirtual: false);
//SafeILGenerator.CallManagedFunction(CallingConventions.VarArgs, FunctionReference.MethodInfo.ReturnType, ParameterTypes, null);
SafeILGenerator.Call(FunctionReference.MethodInfo, FunctionReference.SafeMethodTypeInfo, ParameterTypes);
}
else
{
SafeILGenerator.Call(FunctionReference.MethodInfo, FunctionReference.SafeMethodTypeInfo);
}
}
else
{
throw (new Exception(String.Format("Unknown function '{0}'", IdentifierExpression.Identifier)));
}
//SafeILGenerator.__ILGenerator.Emit(OpCodes.Call
//throw (new NotImplementedException("Function: " + IdentifierExpression.Value));
}
break;
}
}
else
{
throw (new NotImplementedException());
}
}