public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { if (_variadic) { ParameterInfo[] pinfos = _method.GetParameters(); for (int i = 0; i < pinfos.Length - 1; i++) { Expr e = (Expr)_args.nth(i); if (Compiler.MaybePrimitiveType(e) == pinfos[i].ParameterType) { ((MaybePrimitiveExpr)e).EmitUnboxed(RHC.Expression, objx, ilg); } else { e.Emit(RHC.Expression, objx, ilg); HostExpr.EmitUnboxArg(objx, ilg, pinfos[i].ParameterType); } } IPersistentVector restArgs = RT.subvec(_args, pinfos.Length - 1, _args.count()); MethodExpr.EmitArgsAsArray(restArgs, objx, ilg); ilg.EmitCall(Compiler.Method_ArraySeq_create); } else { MethodExpr.EmitTypedArgs(objx, ilg, _method.GetParameters(), _args); } ilg.EmitCall(_method); }
void EmitArgsAndCall(int firstArgToEmit, RHC rhc, ObjExpr objx, CljILGen ilg) { for (int i = firstArgToEmit; i < Math.Min(Compiler.MaxPositionalArity, _args.count()); i++) { Expr e = (Expr)_args.nth(i); e.Emit(RHC.Expression, objx, ilg); } if (_args.count() > Compiler.MaxPositionalArity) { IPersistentVector restArgs = PersistentVector.EMPTY; for (int i = Compiler.MaxPositionalArity; i < _args.count(); i++) { restArgs = restArgs.cons(_args.nth(i)); } MethodExpr.EmitArgsAsArray(restArgs, objx, ilg); } // In JVM. No necessary here. //if (_tailPosition) //{ // ObjMethod method = (ObjMethod)Compiler.MethodVar.deref(); // method.EmitClearThis(ilg); //} MethodInfo mi = Compiler.Methods_IFn_invoke[Math.Min(Compiler.MaxPositionalArity + 1, _args.count())]; ilg.Emit(OpCodes.Callvirt, mi); }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Type targetType = _targetType; GenContext.EmitDebugInfo(ilg, _spanMap); if (targetType != null && _tinfo != null) { _target.Emit(RHC.Expression, objx, ilg); MethodExpr.EmitPrepForCall(ilg, typeof(object), FieldDeclaringType); EmitGet(ilg); HostExpr.EmitBoxReturn(objx, ilg, FieldType); } else { // We could convert this to a dynamic call-site _target.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Ldstr, _memberName); ilg.Emit(OpCodes.Call, Compiler.Method_Reflector_GetInstanceFieldOrProperty); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Type targetType = _targetType; //Type stubType = Compiler.CompileStubOrigClassVar.isBound ? (Type)Compiler.CompileStubOrigClassVar.deref() : null; //if (_targetType == stubType) // targetType = objx.BaseType; GenContext.EmitDebugInfo(ilg, _spanMap); if (targetType != null && _tinfo != null) { _target.Emit(RHC.Expression, objx, ilg); MethodExpr.EmitPrepForCall(ilg, typeof(object), FieldDeclaringType); EmitGet(ilg); HostExpr.EmitBoxReturn(objx, ilg, FieldType); } else { // TODO: convert to dynamic? _target.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Ldstr, _fieldName); ilg.Emit(OpCodes.Call, Compiler.Method_Reflector_GetInstanceFieldOrProperty); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { MethodExpr.EmitArgsAsArray(_keys, objx, ilg); ilg.Emit(OpCodes.Call, Compiler.Method_RT_set); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
internal void EmitIntrinsicPredicate(RHC rhc, ObjExpr objx, CljILGen ilg, Label falseLabel) { GenContext.EmitDebugInfo(ilg, _spanMap); if (_method != null) { MethodExpr.EmitTypedArgs(objx, ilg, _method.GetParameters(), _args); // JVM: clear locals Intrinsics.EmitPred(_method, ilg, falseLabel); } else { throw new InvalidOperationException("Unboxed emit of unknown member"); } }
public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { Type targetType = _targetType; GenContext.EmitDebugInfo(ilg, _spanMap); if (targetType != null && _tinfo != null) { _target.Emit(RHC.Expression, objx, ilg); MethodExpr.EmitPrepForCall(ilg, typeof(object), FieldDeclaringType); EmitGet(ilg); } else { throw new InvalidOperationException("Unboxed emit of unknown member."); } }
public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { // See MethodExpr.EmitComplexCall to see why this is so complicated // Build the parameter list List <ParameterExpression> paramExprs = new List <ParameterExpression>(); List <Type> paramTypes = new List <Type>(); Type paramType = _target.HasClrType && _target.ClrType != null && _target.ClrType.IsPrimitive ? _target.ClrType : typeof(object); ParameterExpression param = Expression.Parameter(paramType); paramExprs.Add(param); paramTypes.Add(paramType); // Build dynamic call and lambda Type returnType = HasClrType ? ClrType : typeof(object); GetMemberBinder binder = new ClojureGetZeroArityMemberBinder(ClojureContext.Default, _memberName, false); #if CLR2 // Not covariant. Sigh. List <Expression> paramsAsExprs = new List <Expression>(paramExprs.Count); paramsAsExprs.AddRange(paramExprs.ToArray()); DynamicExpression dyn = Expression.Dynamic(binder, returnType, paramsAsExprs); #else DynamicExpression dyn = Expression.Dynamic(binder, returnType, paramExprs); #endif LambdaExpression lambda; Type delType; MethodBuilder mbLambda; MethodExpr.EmitDynamicCallPreamble(dyn, _spanMap, "__interop_" + _memberName + RT.nextID(), returnType, paramExprs, paramTypes.ToArray(), ilg, out lambda, out delType, out mbLambda); // Emit target + args (no args, actually) _target.Emit(RHC.Expression, objx, ilg); MethodExpr.EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { bool allKeysConstant = true; bool allConstantKeysUnique = true; IPersistentSet constantKeys = PersistentHashSet.EMPTY; for (int i = 0; i < _keyvals.count(); i += 2) { Expr k = (Expr)_keyvals.nth(i); if (k is LiteralExpr) { object kval = k.Eval(); if (constantKeys.contains(kval)) { allConstantKeysUnique = false; } else { constantKeys = (IPersistentSet)constantKeys.cons(kval); } } else { allKeysConstant = false; } } MethodExpr.EmitArgsAsArray(_keyvals, objx, ilg); if ((allKeysConstant && allConstantKeysUnique) || (_keyvals.count() <= 2)) { ilg.EmitCall(Compiler.Method_RT_mapUniqueKeys); } else { ilg.EmitCall(Compiler.Method_RT_map); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { if (_args.count() <= Tuple.MAX_SIZE) { for (int i = 0; i < _args.count(); i++) { ((Expr)_args.nth(i)).Emit(RHC.Expression, objx, ilg); } ilg.Emit(OpCodes.Call, Compiler.Methods_CreateTuple[_args.count()]); } else { MethodExpr.EmitArgsAsArray(_args, objx, ilg); ilg.Emit(OpCodes.Call, Compiler.Method_RT_vector); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { Type targetType = _targetType; //Type stubType = Compiler.CompileStubOrigClassVar.isBound ? (Type)Compiler.CompileStubOrigClassVar.deref() : null; //if (_targetType == stubType) // targetType = objx.BaseType; GenContext.EmitDebugInfo(ilg, _spanMap); if (targetType != null && _tinfo != null) { _target.Emit(RHC.Expression, objx, ilg); MethodExpr.EmitPrepForCall(ilg, typeof(object), FieldDeclaringType); EmitGet(ilg); } else { throw new InvalidOperationException("Unboxed emit of unknown member."); } }
void EmitProto(RHC rhc, ObjExpr objx, CljILGen ilg) { Label onLabel = ilg.DefineLabel(); Label callLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); Var v = ((VarExpr)_fexpr).Var; Expr e = (Expr)_args.nth(0); e.Emit(RHC.Expression, objx, ilg); // target ilg.Emit(OpCodes.Dup); // target, target LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(targetTemp, "target"); ilg.Emit(OpCodes.Stloc, targetTemp); // target ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class ilg.EmitLoadArg(0); // class, this ilg.EmitFieldGet(objx.CachedTypeField(_siteIndex)); // class, cached-class ilg.Emit(OpCodes.Beq, callLabel); // if (_protocolOn != null) { ilg.Emit(OpCodes.Ldloc, targetTemp); // target ilg.Emit(OpCodes.Isinst, _protocolOn); // null or target ilg.Emit(OpCodes.Ldnull); // (null or target), null ilg.Emit(OpCodes.Cgt_Un); // (0 or 1) ilg.Emit(OpCodes.Brtrue, onLabel); } ilg.Emit(OpCodes.Ldloc, targetTemp); // target ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class LocalBuilder typeTemp = ilg.DeclareLocal(typeof(Type)); GenContext.SetLocalName(typeTemp, "type"); ilg.Emit(OpCodes.Stloc, typeTemp); // (typeType <= class) ilg.EmitLoadArg(0); // this ilg.Emit(OpCodes.Ldloc, typeTemp); // this, class ilg.EmitFieldSet(objx.CachedTypeField(_siteIndex)); // ilg.MarkLabel(callLabel); objx.EmitVar(ilg, v); // var ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn ilg.Emit(OpCodes.Castclass, typeof(AFunction)); ilg.Emit(OpCodes.Ldloc, targetTemp); // proto-fn, target EmitArgsAndCall(1, rhc, objx, ilg); ilg.Emit(OpCodes.Br, endLabel); ilg.MarkLabel(onLabel); ilg.Emit(OpCodes.Ldloc, targetTemp); // target if (_protocolOn != null) { ilg.Emit(OpCodes.Castclass, _protocolOn); MethodExpr.EmitTypedArgs(objx, ilg, _onMethod.GetParameters(), RT.subvec(_args, 1, _args.count())); //if (rhc == RHC.Return) //{ // ObjMethod2 method = (ObjMethod)Compiler.MethodVar.deref(); // method.EmitClearLocals(context); //} ilg.Emit(OpCodes.Callvirt, _onMethod); HostExpr.EmitBoxReturn(objx, ilg, _onMethod.ReturnType); } ilg.MarkLabel(endLabel); }
// TODO: See if it is worth removing the code duplication with MethodExp.GenDlr. private Expression GenerateComplexCall(RHC rhc, ObjExpr objx, GenContext context) { Expression call; Expression target = GenTargetExpression(objx, context); List <Expression> exprs = new List <Expression>(_args.Count); List <ParameterExpression> sbParams = new List <ParameterExpression>(); List <Expression> sbInits = new List <Expression>(); List <Expression> sbTransfers = new List <Expression>(); MethodExpr.GenerateComplexArgList(objx, context, _args, out exprs, out sbParams, out sbInits, out sbTransfers); Expression[] argExprs = ClrExtensions.ArrayInsert <Expression>(target, exprs); Type returnType = this.ClrType; Type stubType = Compiler.CompileStubOrigClassVar.isBound ? (Type)Compiler.CompileStubOrigClassVar.deref() : null; if (returnType == stubType) { returnType = objx.BaseType; } // TODO: get rid of Default CreateInstanceBinder binder = new ClojureCreateInstanceBinder(ClojureContext.Default, _args.Count); DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), argExprs); // I'd like to use returnType in place of typeof(object) in the previous, // But I can't override ReturnType in DefaultCreateInstanceBinder and this causes an error. // Look for the conversion below. //if (context.Mode == CompilerMode.File) if (context.DynInitHelper != null) { call = context.DynInitHelper.ReduceDyn(dyn); } else { call = dyn; } call = Expression.Convert(call, returnType); if (sbParams.Count > 0) { // We have ref/out params. Construct the complicated call; ParameterExpression callValParam = Expression.Parameter(returnType, "__callVal"); ParameterExpression[] allParams = ClrExtensions.ArrayInsert <ParameterExpression>(callValParam, sbParams); call = Expression.Block( returnType, allParams, Expression.Block(sbInits), Expression.Assign(callValParam, call), Expression.Block(sbTransfers), callValParam); } return(call); }
private void EmitComplexCall(RHC rhc, ObjExpr objx, CljILGen ilg) { // See the notes on MethodExpr.EmitComplexCall on why this is so complicated List <ParameterExpression> paramExprs = new List <ParameterExpression>(_args.Count + 1); List <Type> paramTypes = new List <Type>(_args.Count + 1); paramExprs.Add(Expression.Parameter(typeof(Type))); paramTypes.Add(typeof(Type)); int i = 0; foreach (HostArg ha in _args) { i++; Expr e = ha.ArgExpr; Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object); switch (ha.ParamType) { case HostArg.ParameterType.ByRef: { Type byRefType = argType.MakeByRefType(); paramExprs.Add(Expression.Parameter(byRefType, ha.LocalBinding.Name)); paramTypes.Add(byRefType); break; } case HostArg.ParameterType.Standard: if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr) { paramExprs.Add(Expression.Parameter(argType, ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i)); paramTypes.Add(argType); } else { paramExprs.Add(Expression.Parameter(typeof(object), ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i)); paramTypes.Add(typeof(object)); } break; default: throw Util.UnreachableCode(); } } // Build dynamic call and lambda Type returnType = HasClrType ? ClrType : typeof(object); CreateInstanceBinder binder = new ClojureCreateInstanceBinder(ClojureContext.Default, _args.Count); #if CLR2 // Not covariant. Sigh. List <Expression> paramsAsExprs = new List <Expression>(paramExprs.Count); paramsAsExprs.AddRange(paramExprs.ToArray()); DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramsAsExprs); #else DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramExprs); #endif LambdaExpression lambda; Type delType; MethodBuilder mbLambda; MethodExpr.EmitDynamicCallPreamble(dyn, _spanMap, "__interop_ctor_" + RT.nextID(), returnType, paramExprs, paramTypes.ToArray(), ilg, out lambda, out delType, out mbLambda); // Emit target + args EmitTargetExpression(objx, ilg); i = 0; foreach (HostArg ha in _args) { i++; Expr e = ha.ArgExpr; Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object); switch (ha.ParamType) { case HostArg.ParameterType.ByRef: MethodExpr.EmitByRefArg(ha, objx, ilg); break; case HostArg.ParameterType.Standard: if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr) { ((MaybePrimitiveExpr)ha.ArgExpr).EmitUnboxed(RHC.Expression, objx, ilg); } else { ha.ArgExpr.Emit(RHC.Expression, objx, ilg); } break; default: throw Util.UnreachableCode(); } } MethodExpr.EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg); }
private void EmitParamsForMethod(ObjExpr objx, CljILGen ilg) { ParameterInfo[] pis = _ctor.GetParameters(); MethodExpr.EmitTypedArgs(objx, ilg, pis, _args); }