void EmitShiftMask(CljILGen ilg) { if (IsShiftMasked) { ilg.EmitInt(_shift); ilg.Emit(OpCodes.Shr); ilg.EmitInt(_mask); ilg.Emit(OpCodes.And); } }
internal static void EmitArgsAsArray(IPersistentVector args, ObjExpr objx, CljILGen ilg) { ilg.EmitInt(args.count()); ilg.Emit(OpCodes.Newarr, typeof(Object)); for (int i = 0; i < args.count(); i++) { ilg.Emit(OpCodes.Dup); ilg.EmitInt(i); ((Expr)args.nth(i)).Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stelem_Ref); } }
private void EmitListAsObjectArray(object value, CljILGen ilg) { ICollection coll = (ICollection)value; ilg.EmitInt(coll.Count); ilg.Emit(OpCodes.Newarr, typeof(Object)); int i = 0; foreach (Object item in coll) { ilg.Emit(OpCodes.Dup); ilg.EmitInt(i++); EmitValue(item, ilg); //HostExpr.EmitBoxReturn(this, ilg, item.GetType()); ilg.Emit(OpCodes.Stelem_Ref); } }
protected static void EmitHasArityMethod(TypeBuilder tb, IList <int> arities, bool isVariadic, int reqArity) { // TODO: Convert to a Switch instruction MethodBuilder mb = tb.DefineMethod( "HasArity", MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(bool), new Type[] { typeof(int) }); CljILGen gen = new CljILGen(mb.GetILGenerator()); Label falseLabel = gen.DefineLabel(); Label trueLabel = gen.DefineLabel(); if (isVariadic) { gen.EmitLoadArg(1); gen.EmitInt(reqArity); gen.Emit(OpCodes.Bge, trueLabel); } if (arities != null) { foreach (int i in arities) { gen.EmitLoadArg(1); gen.EmitInt(i); gen.Emit(OpCodes.Beq, trueLabel); } } gen.MarkLabel(falseLabel); gen.EmitBoolean(false); gen.Emit(OpCodes.Ret); gen.MarkLabel(trueLabel); gen.EmitBoolean(true); gen.Emit(OpCodes.Ret); }
static void EmitGetRequiredArityMethod(TypeBuilder tb, int requiredArity) { MethodBuilder mb = tb.DefineMethod( "getRequiredArity", MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(int), Type.EmptyTypes); CljILGen gen = new CljILGen(mb.GetILGenerator()); gen.EmitInt(requiredArity); gen.Emit(OpCodes.Ret); }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]); if (primType != null) { HostExpr.EmitBoxReturn(this, ilg, primType); } // TODO: ONCEONLY? } else // FnMode.Light { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); } } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) { HostExpr.EmitBoxReturn(this, ilg, primType); } } }
static void EmitPrimitive(CljILGen ilg, object val) { switch (Type.GetTypeCode(val.GetType())) { case TypeCode.Boolean: ilg.EmitBoolean((bool)val); break; case TypeCode.Byte: ilg.EmitByte((byte)val); break; case TypeCode.Char: ilg.EmitChar((char)val); break; case TypeCode.Decimal: ilg.EmitDecimal((decimal)val); break; case TypeCode.Double: ilg.EmitDouble((double)val); break; case TypeCode.Int16: ilg.EmitShort((short)val); break; case TypeCode.Int32: ilg.EmitInt((int)val); break; case TypeCode.Int64: ilg.EmitLong((long)val); break; case TypeCode.SByte: ilg.EmitSByte((sbyte)val); break; case TypeCode.Single: ilg.EmitSingle((float)val); break; case TypeCode.UInt16: ilg.EmitUShort((ushort)val); break; case TypeCode.UInt32: ilg.EmitUInt((uint)val); break; case TypeCode.UInt64: ilg.EmitULong((ulong)val); break; default: throw new InvalidOperationException("Unknown constant type in EmitPrimitive"); } }
static public void EmitDynamicCallPreamble(DynamicExpression dyn, IPersistentMap spanMap, string methodName, Type returnType, List <ParameterExpression> paramExprs, Type[] paramTypes, CljILGen ilg, out LambdaExpression lambda, out Type delType, out MethodBuilder mbLambda) { Expression call = dyn; GenContext context = Compiler.CompilerContextVar.deref() as GenContext; if (context != null && context.DynInitHelper != null) { call = context.DynInitHelper.ReduceDyn(dyn); } if (returnType == typeof(void)) { call = Expression.Block(call, Expression.Default(typeof(object))); returnType = typeof(object); } else if (returnType != call.Type) { call = Expression.Convert(call, returnType); } call = GenContext.AddDebugInfo(call, spanMap); delType = Microsoft.Scripting.Generation.Snippets.Shared.DefineDelegate("__interop__", returnType, paramTypes); lambda = Expression.Lambda(delType, call, paramExprs); mbLambda = null; if (context == null) { // light compile Delegate d = lambda.Compile(); int key = RT.nextID(); CacheDelegate(key, d); ilg.EmitInt(key); ilg.Emit(OpCodes.Call, Method_MethodExpr_GetDelegate); ilg.Emit(OpCodes.Castclass, delType); } else { mbLambda = context.TB.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, returnType, paramTypes); lambda.CompileToMethod(mbLambda); } }
public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { GenContext.EmitDebugInfo(ilg, _spanMap); if (_tinfo.IsLiteral) { // literal fields need to be inlined directly in here... We use GetRawConstant // which will work even in partial trust if the constant is protected. object value = _tinfo.GetRawConstantValue(); switch (Type.GetTypeCode(_tinfo.FieldType)) { case TypeCode.Boolean: if ((bool)value) { ilg.Emit(OpCodes.Ldc_I4_1); } else { ilg.Emit(OpCodes.Ldc_I4_0); } break; case TypeCode.Byte: ilg.EmitInt((int)(byte)value); break; case TypeCode.Char: ilg.EmitInt((int)(char)value); break; case TypeCode.Double: ilg.EmitDouble((double)value); break; case TypeCode.Int16: ilg.EmitInt((int)(short)value); break; case TypeCode.Int32: ilg.EmitInt((int)value); break; case TypeCode.Int64: ilg.EmitLong((long)value); break; case TypeCode.SByte: ilg.EmitInt((int)(sbyte)value); break; case TypeCode.Single: ilg.EmitSingle((float)value); break; case TypeCode.String: ilg.EmitString((string)value); break; case TypeCode.UInt16: ilg.EmitInt((int)(ushort)value); break; case TypeCode.UInt32: ilg.Emit(OpCodes.Ldc_I4, (uint)value); break; case TypeCode.UInt64: ilg.Emit(OpCodes.Ldc_I8, (ulong)value); break; } } else { ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldGet(_tinfo); } }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); if (lb.PrimitiveType != null) { ilg.Emit(OpCodes.Unbox, lb.PrimitiveType); } } } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } }
internal void EmitConstant(CljILGen ilg, int id, object val) { if (_fnMode == Ast.FnMode.Light) { if (val == null) { ilg.EmitNull(); } if (val.GetType().IsPrimitive) { EmitPrimitive(ilg, val); ilg.Emit(OpCodes.Box, val.GetType()); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Constants); ilg.EmitInt(id); ilg.EmitLoadElement(typeof(Object)); ilg.Emit(OpCodes.Castclass, ConstantType(id)); } } else { FieldBuilder fb = null; if (_fnMode == FnMode.Full && ConstantFields != null && ConstantFields.TryGetValue(id, out fb)) { ilg.Emit(OpCodes.Ldsfld, fb); } else { EmitValue(val, ilg); } } }
protected static void EmitHasArityMethod(TypeBuilder tb, IList<int> arities, bool isVariadic, int reqArity) { // TODO: Convert to a Switch instruction MethodBuilder mb = tb.DefineMethod( "HasArity", MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(bool), new Type[] { typeof(int) }); CljILGen gen = new CljILGen(mb.GetILGenerator()); Label falseLabel = gen.DefineLabel(); Label trueLabel = gen.DefineLabel(); if (isVariadic) { gen.EmitLoadArg(1); gen.EmitInt(reqArity); gen.Emit(OpCodes.Bge, trueLabel); } if (arities != null) { foreach (int i in arities) { gen.EmitLoadArg(1); gen.EmitInt(i); gen.Emit(OpCodes.Beq, trueLabel); } } gen.MarkLabel(falseLabel); gen.EmitBoolean(false); gen.Emit(OpCodes.Ret); gen.MarkLabel(trueLabel); gen.EmitBoolean(true); gen.Emit(OpCodes.Ret); }
internal void EmitConstant(CljILGen ilg, int id, object val) { if (_fnMode == Ast.FnMode.Light) { if (val == null) { ilg.EmitNull(); } if (val.GetType().IsPrimitive) { EmitPrimitive(ilg, val); ilg.Emit(OpCodes.Box,val.GetType()); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Constants); ilg.EmitInt(id); ilg.EmitLoadElement(typeof(Object)); ilg.Emit(OpCodes.Castclass, ConstantType(id)); } } else { FieldBuilder fb = null; if (_fnMode == FnMode.Full && ConstantFields != null && ConstantFields.TryGetValue(id, out fb)) { ilg.MaybeEmitVolatileOp(fb); ilg.Emit(OpCodes.Ldsfld, fb); } else EmitValue(val, ilg); } }
public void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { GenContext.EmitDebugInfo(ilg, _sourceSpan); Label defaultLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); SortedDictionary <int, Label> labels = new SortedDictionary <int, Label>(); foreach (int i in _tests.Keys) { labels[i] = ilg.DefineLabel(); } Type primExprType = Compiler.MaybePrimitiveType(_expr); if (_testType == _intKey) { EmitExprForInts(objx, ilg, primExprType, defaultLabel); } else { EmitExprForHashes(objx, ilg); } if (_switchType == _sparseKey) { Label[] la = labels.Values.ToArray <Label>(); ilg.Emit(OpCodes.Switch, la); ilg.Emit(OpCodes.Br, defaultLabel); } else { Label[] la = new Label[(_high - _low) + 1]; for (int i = _low; i <= _high; i++) { la[i - _low] = labels.ContainsKey(i) ? labels[i] : defaultLabel; } ilg.EmitInt(_low); ilg.Emit(OpCodes.Sub); ilg.Emit(OpCodes.Switch, la); ilg.Emit(OpCodes.Br, defaultLabel); } foreach (int i in labels.Keys) { ilg.MarkLabel(labels[i]); if (_testType == _intKey) { EmitThenForInts(objx, ilg, primExprType, _tests[i], _thens[i], defaultLabel, emitUnboxed); } else if ((bool)RT.contains(_skipCheck, i)) { EmitExpr(objx, ilg, _thens[i], emitUnboxed); } else { EmitThenForHashes(objx, ilg, _tests[i], _thens[i], defaultLabel, emitUnboxed); } if (_thens[i].HasNormalExit()) { ilg.Emit(OpCodes.Br, endLabel); } } ilg.MarkLabel(defaultLabel); EmitExpr(objx, ilg, _defaultExpr, emitUnboxed); ilg.MarkLabel(endLabel); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
static void DefineCtors(TypeBuilder proxyTB, Type superClass, string initName, string postInitName, ISeq ctors, ISeq ctorTypes, FieldBuilder initFB, FieldBuilder postInitFB, FieldBuilder stateFB, string factoryName) { ISeq s1 = ctors; for (ISeq s = ctorTypes; s != null; s = s.next()) { // TODO: Get rid of this mess by making sure the metadata on the keys of the constructors map gets copied to the constructor-types map. Sigh. IPersistentMap ctorAttributes = GenInterface.ExtractAttributes(RT.meta(((IMapEntry)s1.first()).key())); s1 = s1.next(); IMapEntry me = (IMapEntry)s.first(); ISeq thisParamTypesV = (ISeq)me.key(); ISeq baseParamTypesV = (ISeq)me.val(); Type[] thisParamTypes = CreateTypeArray(thisParamTypesV); Type[] baseParamTypes = CreateTypeArray(baseParamTypesV); BindingFlags flags = BindingFlags.CreateInstance| BindingFlags.NonPublic| BindingFlags.Public| BindingFlags.Instance; ConstructorInfo superCtor = superClass.GetConstructor(flags,null,baseParamTypes,null); if (superCtor == null || superCtor.IsPrivate) throw new InvalidOperationException("Base class constructor missing or private"); ConstructorBuilder cb = proxyTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, thisParamTypes); GenInterface.SetCustomAttributes(cb, ctorAttributes); CljILGen gen = new CljILGen(cb.GetILGenerator()); Label noInitLabel = gen.DefineLabel(); Label noPostInitLabel = gen.DefineLabel(); Label endPostInitLabel = gen.DefineLabel(); Label endLabel = gen.DefineLabel(); LocalBuilder locSuperArgs = gen.DeclareLocal(typeof(object)); LocalBuilder locInitVal = gen.DeclareLocal(typeof(object)); if (initFB != null) { // init supplied EmitGetVar(gen, initFB); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, noInitLabel); gen.Emit(OpCodes.Castclass, typeof(IFn)); // box init args for (int i = 0; i < thisParamTypes.Length; i++) { gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (thisParamTypes[i].IsValueType) gen.Emit(OpCodes.Box,thisParamTypes[i]); } gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length]); // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length]); // Expecting: [[super-ctor-args...] state] // store the init return in a local gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Stloc,locInitVal); // store the first element in a local gen.EmitInt(0); // gen.Emit(OpCodes.Ldc_I4_0); gen.EmitCall(Method_RT_nth); // gen.Emit(OpCodes.Call, Method_RT_nth); gen.Emit(OpCodes.Stloc, locSuperArgs); // Stack this + super-ctor-args + call base-class ctor. gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < baseParamTypes.Length; i++) { gen.Emit(OpCodes.Ldloc, locSuperArgs); gen.EmitInt(i); // gen.Emit(OpCodes.Ldc_I4, i); gen.EmitCall(Method_RT_nth); // gen.Emit(OpCodes.Call, Method_RT_nth); if (baseParamTypes[i].IsValueType) gen.Emit(OpCodes.Unbox_Any, baseParamTypes[i]); else gen.Emit(OpCodes.Castclass, baseParamTypes[i]); } gen.Emit(OpCodes.Call, superCtor); if (stateFB != null) { gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldloc, locInitVal); gen.EmitInt(1); // gen.Emit(OpCodes.Ldc_I4_1); gen.EmitCall(Method_RT_nth); // gen.Emit(OpCodes.Call, Method_RT_nth); gen.Emit(OpCodes.Castclass, typeof(object)); gen.EmitFieldSet(stateFB); // gen.Emit(OpCodes.Stfld, stateFB); } gen.Emit(OpCodes.Br_S, endLabel); // No init found gen.MarkLabel(noInitLabel); gen.Emit(OpCodes.Pop); EmitUnsupported(gen, initName); gen.MarkLabel(endLabel); } else // no InitFB supplied. { bool ok = thisParamTypes.Length == baseParamTypes.Length; for (int i = 0; ok && i < thisParamTypes.Length; i++) ok = baseParamTypes[i].IsAssignableFrom(thisParamTypes[i]); if (!ok) throw new InvalidOperationException(":init not specified, but ctor and super ctor args differ"); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for ( int i=0; i< thisParamTypes.Length; i++ ) { gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (baseParamTypes[i] != thisParamTypes[i]) gen.Emit(OpCodes.Castclass, baseParamTypes[i]); } gen.Emit(OpCodes.Call, superCtor); } if (postInitFB != null) { // post-init supplied EmitGetVar(gen, postInitFB); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, noPostInitLabel); gen.Emit(OpCodes.Castclass, typeof(IFn)); // box init args gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < thisParamTypes.Length; i++) { gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (thisParamTypes[i].IsValueType) gen.Emit(OpCodes.Box, thisParamTypes[i]); gen.Emit(OpCodes.Castclass, thisParamTypes[i]); } gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]); // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]); gen.Emit(OpCodes.Pop); gen.Emit(OpCodes.Br_S, endPostInitLabel); // no post-init found gen.MarkLabel(noPostInitLabel); gen.Emit(OpCodes.Pop); EmitUnsupported(gen,postInitName + " not defined"); gen.MarkLabel(endPostInitLabel); } gen.Emit(OpCodes.Ret); if (!String.IsNullOrEmpty(factoryName)) { MethodBuilder factoryMB = proxyTB.DefineMethod(factoryName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, proxyTB, thisParamTypes); CljILGen genf = new CljILGen(factoryMB.GetILGenerator()); LocalBuilder[] locals = new LocalBuilder[thisParamTypes.Length]; for (int i = 0; i < thisParamTypes.Length; i++) { locals[i] = genf.DeclareLocal(thisParamTypes[i]); genf.EmitLoadArg(i); // genf.Emit(OpCodes.Ldarg, i); genf.Emit(OpCodes.Stloc, locals[i]); } for (int i = 0; i < thisParamTypes.Length; i++) genf.EmitLoadArg(i); // genf.Emit(OpCodes.Ldarg, i); genf.EmitNew(cb); // genf.Emit(OpCodes.Newobj, cb); genf.Emit(OpCodes.Ret); } } }
public void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { GenContext.EmitDebugInfo(ilg, _sourceSpan); Label defaultLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); SortedDictionary<int, Label> labels = new SortedDictionary<int, Label>(); foreach (int i in _tests.Keys) labels[i] = ilg.DefineLabel(); // TODO: debug info Type primExprType = Compiler.MaybePrimitiveType(_expr); if (_testType == _intKey) EmitExprForInts(objx, ilg, primExprType, defaultLabel); else EmitExprForHashes(objx, ilg); if (_switchType == _sparseKey) { Label[] la = labels.Values.ToArray<Label>(); ilg.Emit(OpCodes.Switch, la); ilg.Emit(OpCodes.Br, defaultLabel); } else { Label[] la = new Label[(_high - _low) + 1]; for (int i = _low; i <= _high; i++) la[i - _low] = labels.ContainsKey(i) ? labels[i] : defaultLabel; ilg.EmitInt(_low); ilg.Emit(OpCodes.Sub); ilg.Emit(OpCodes.Switch, la); ilg.Emit(OpCodes.Br, defaultLabel); } foreach (int i in labels.Keys) { ilg.MarkLabel(labels[i]); if (_testType == _intKey) EmitThenForInts(objx, ilg, primExprType, _tests[i], _thens[i], defaultLabel, emitUnboxed); else if ((bool)RT.contains(_skipCheck, i)) EmitExpr(objx, ilg, _thens[i], emitUnboxed); else EmitThenForHashes(objx, ilg, _tests[i], _thens[i], defaultLabel, emitUnboxed); if ( _thens[i].HasNormalExit() ) ilg.Emit(OpCodes.Br, endLabel); } ilg.MarkLabel(defaultLabel); EmitExpr(objx, ilg, _defaultExpr, emitUnboxed); ilg.MarkLabel(endLabel); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); if (lb.PrimitiveType != null) ilg.Emit(OpCodes.Unbox, lb.PrimitiveType); } } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else ilg.Emit(OpCodes.Ldloc, lb.LocalVar); }
private void EmitGetCompiledConstants(CljILGen ilg) { ilg.EmitInt(DynMethodMapKey); ilg.Emit(OpCodes.Call, Method_FnExpr_GetCompiledConstants); }
private void EmitGetDynMethod(int arity, CljILGen ilg) { ilg.EmitInt(DynMethodMapKey); ilg.EmitInt(arity); ilg.Emit(OpCodes.Call,Method_FnExpr_GetDynMethod); }
public static void EmitDynamicCallPreamble(DynamicExpression dyn, IPersistentMap spanMap, string methodName, Type returnType, List<ParameterExpression> paramExprs, Type[] paramTypes, CljILGen ilg, out LambdaExpression lambda, out Type delType, out MethodBuilder mbLambda) { Expression call = dyn; GenContext context = Compiler.CompilerContextVar.deref() as GenContext; if (context != null && context.DynInitHelper != null) call = context.DynInitHelper.ReduceDyn(dyn); if (returnType == typeof(void)) { call = Expression.Block(call, Expression.Default(typeof(object))); returnType = typeof(object); } else if (returnType != call.Type) { call = Expression.Convert(call, returnType); } call = GenContext.AddDebugInfo(call, spanMap); delType = Microsoft.Scripting.Generation.Snippets.Shared.DefineDelegate("__interop__", returnType, paramTypes); lambda = Expression.Lambda(delType, call, paramExprs); mbLambda = null; if (context == null) { // light compile Delegate d = lambda.Compile(); int key = RT.nextID(); CacheDelegate(key, d); ilg.EmitInt(key); ilg.Emit(OpCodes.Call, Method_MethodExpr_GetDelegate); ilg.Emit(OpCodes.Castclass, delType); } else { mbLambda = context.TB.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, returnType, paramTypes); lambda.CompileToMethod(mbLambda); } }
protected void EmitValue(object value, CljILGen ilg) { bool partial = true; if (value == null) ilg.Emit(OpCodes.Ldnull); else if (value is String) ilg.Emit(OpCodes.Ldstr, (String)value); else if (value is Boolean) { ilg.EmitBoolean((Boolean)value); ilg.Emit(OpCodes.Box,typeof(bool)); } else if (value is Int32) { ilg.EmitInt((int)value); ilg.Emit(OpCodes.Box, typeof(int)); } else if (value is Int64) { ilg.EmitLong((long)value); ilg.Emit(OpCodes.Box, typeof(long)); } else if (value is Double) { ilg.EmitDouble((double)value); ilg.Emit(OpCodes.Box, typeof(double)); } else if (value is Char) { ilg.EmitChar((char)value); ilg.Emit(OpCodes.Box,typeof(char)); } else if (value is Type) { Type t = (Type)value; if (t.IsValueType) ilg.EmitType(t); else { //ilg.EmitString(Compiler.DestubClassName(((Type)value).FullName)); ilg.EmitString(((Type)value).FullName); ilg.EmitCall(Compiler.Method_RT_classForName); } } else if (value is Symbol) { Symbol sym = (Symbol)value; if (sym.Namespace == null) ilg.EmitNull(); else ilg.EmitString(sym.Namespace); ilg.EmitString(sym.Name); ilg.EmitCall(Compiler.Method_Symbol_intern2); } else if (value is Keyword) { Keyword keyword = (Keyword)value; if (keyword.Namespace == null) ilg.EmitNull(); else ilg.EmitString(keyword.Namespace); ilg.EmitString(keyword.Name); ilg.EmitCall(Compiler.Method_RT_keyword); } else if (value is Var) { Var var = (Var)value; ilg.EmitString(var.Namespace.Name.ToString()); ilg.EmitString(var.Symbol.Name.ToString()); ilg.EmitCall(Compiler.Method_RT_var2); } else if (value is IType) { IPersistentVector fields = (IPersistentVector)Reflector.InvokeStaticMethod(value.GetType(), "getBasis", Type.EmptyTypes); for (ISeq s = RT.seq(fields); s != null; s = s.next()) { Symbol field = (Symbol)s.first(); Type k = Compiler.TagType(Compiler.TagOf(field)); object val = Reflector.GetInstanceFieldOrProperty(value, field.Name); EmitValue(val, ilg); if (k.IsPrimitive) { ilg.Emit(OpCodes.Castclass, k); } } ConstructorInfo cinfo = value.GetType().GetConstructors()[0]; ilg.EmitNew(cinfo); } else if (value is IRecord) { //MethodInfo[] minfos = value.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public); EmitValue(PersistentArrayMap.create((IDictionary)value), ilg); MethodInfo createMI = value.GetType().GetMethod("create", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { typeof(IPersistentMap) }, null); ilg.EmitCall(createMI); } else if (value is IPersistentMap) { IPersistentMap map = (IPersistentMap)value; List<object> entries = new List<object>(map.count() * 2); foreach (IMapEntry entry in map) { entries.Add(entry.key()); entries.Add(entry.val()); } EmitListAsObjectArray(entries, ilg); ilg.EmitCall(Compiler.Method_RT_map); } else if (value is IPersistentVector) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_RT_vector); } else if (value is PersistentHashSet) { ISeq vs = RT.seq(value); if (vs == null) ilg.EmitFieldGet(Compiler.Method_PersistentHashSet_EMPTY); else { EmitListAsObjectArray(vs, ilg); ilg.EmitCall(Compiler.Method_PersistentHashSet_create); } } else if (value is ISeq || value is IPersistentList) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_PersistentList_create); } else if (value is Regex) { ilg.EmitString(((Regex)value).ToString()); ilg.EmitNew(Compiler.Ctor_Regex_1); } else { string cs = null; try { cs = RT.printString(value); } catch (Exception) { throw new InvalidOperationException(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", value)); } if (cs.Length == 0) throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + value)); if (cs.StartsWith("#<")) throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + cs)); ilg.EmitString(cs); ilg.EmitCall(Compiler.Method_RT_readString); partial = false; } if (partial) { if (value is IObj && RT.count(((IObj)value).meta()) > 0) { ilg.Emit(OpCodes.Castclass, typeof(IObj)); Object m = ((IObj)value).meta(); EmitValue(Compiler.ElideMeta(m), ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.Emit(OpCodes.Callvirt, Compiler.Method_IObj_withMeta); } } }
static void EmitPrimitive(CljILGen ilg, object val) { switch (Type.GetTypeCode(val.GetType()) ) { case TypeCode.Boolean: ilg.EmitBoolean((bool)val); break; case TypeCode.Byte: ilg.EmitByte((byte)val); break; case TypeCode.Char: ilg.EmitChar((char)val); break; case TypeCode.Decimal: ilg.EmitDecimal((decimal)val); break; case TypeCode.Double: ilg.EmitDouble((double)val); break; case TypeCode.Int16: ilg.EmitShort((short)val); break; case TypeCode.Int32: ilg.EmitInt((int)val); break; case TypeCode.Int64: ilg.EmitLong((long)val); break; case TypeCode.SByte: ilg.EmitSByte((sbyte)val); break; case TypeCode.Single: ilg.EmitSingle((float)val); break; case TypeCode.UInt16: ilg.EmitUShort((ushort)val); break; case TypeCode.UInt32: ilg.EmitUInt((uint)val); break; case TypeCode.UInt64: ilg.EmitULong((ulong)val); break; default: throw new InvalidOperationException("Unknown constant type in EmitPrimitive"); } }
void LightEmit(RHC rhc, ObjExpr objx, CljILGen ilg) { //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any //objx arg is enclosing objx, not this // Create the function instance LocalBuilder fnLocal = ilg.DeclareLocal(CompiledType); if (CompiledType == typeof(RestFnImpl)) { ilg.EmitInt(_variadicMethod.RequiredArity); ilg.EmitNew(Compiler.Ctor_RestFnImpl_1); } else { ilg.EmitNew(Compiler.Ctor_AFnImpl); } ilg.Emit(OpCodes.Stloc, fnLocal); //ilg.EmitString(String.Format("Creating fn {0}", Name)); //ilg.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(string) })); // Set up the methods for (ISeq s = RT.seq(_methods); s != null; s = s.next()) { FnMethod method = (FnMethod)s.first(); int key = GetMethodKey(method); string fieldName = IsVariadic && method.IsVariadic ? "_fnDo" + (key - 1) // because key is arity+1 for variadic : "_fn" + key; FieldInfo fi = CompiledType.GetField(fieldName); ilg.Emit(OpCodes.Ldloc, fnLocal); EmitGetDynMethod(key, ilg); ilg.EmitType(fi.FieldType); ilg.Emit(OpCodes.Ldloc, fnLocal); ilg.Emit(OpCodes.Callvirt, Method_DynamicMethod_CreateDelegate); ilg.Emit(OpCodes.Castclass, fi.FieldType); ilg.EmitFieldSet(fi); } // setup the constants and locals ilg.Emit(OpCodes.Ldloc, fnLocal); if (Constants.count() > 0) { EmitGetCompiledConstants(ilg); } else { ilg.EmitInt(0); ilg.EmitArray(typeof(Object[])); } if (Closes.count() > 0) { int maxIndex = Closes.Max(c => ((LocalBinding)c.key()).Index); ilg.EmitInt(maxIndex + 1); ilg.Emit(OpCodes.Newarr, typeof(object)); for (ISeq s = RT.keys(Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); ilg.Emit(OpCodes.Dup); ilg.EmitInt(lb.Index); objx.EmitLocal(ilg, lb); ilg.EmitStoreElement(typeof(object)); } } else { ilg.EmitInt(0); ilg.EmitArray(typeof(Object[])); } // Create the closure ilg.EmitNew(Compiler.Ctor_Closure_2); // Assign the clojure ilg.EmitCall(Compiler.Method_IFnClosure_SetClosure); // Leave the instance on the stack. ilg.Emit(OpCodes.Ldloc, fnLocal); }
private void EmitGetDynMethod(int arity, CljILGen ilg) { ilg.EmitInt(DynMethodMapKey); ilg.EmitInt(arity); ilg.Emit(OpCodes.Call, Method_FnExpr_GetDynMethod); }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); // TODO: ONCEONLY? } else // FnMode.Light { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); } } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); } }
protected void EmitValue(object value, CljILGen ilg) { bool partial = true; if (value == null) { ilg.Emit(OpCodes.Ldnull); } else if (value is String) { ilg.Emit(OpCodes.Ldstr, (String)value); } else if (value is Boolean) { ilg.EmitBoolean((Boolean)value); ilg.Emit(OpCodes.Box, typeof(bool)); } else if (value is Int32) { ilg.EmitInt((int)value); ilg.Emit(OpCodes.Box, typeof(int)); } else if (value is Int64) { ilg.EmitLong((long)value); ilg.Emit(OpCodes.Box, typeof(long)); } else if (value is Double) { ilg.EmitDouble((double)value); ilg.Emit(OpCodes.Box, typeof(double)); } else if (value is Char) { ilg.EmitChar((char)value); ilg.Emit(OpCodes.Box, typeof(char)); } else if (value is Type) { Type t = (Type)value; if (t.IsValueType) { ilg.EmitType(t); } else { //ilg.EmitString(Compiler.DestubClassName(((Type)value).FullName)); ilg.EmitString(((Type)value).FullName); ilg.EmitCall(Compiler.Method_RT_classForName); } } else if (value is Symbol) { Symbol sym = (Symbol)value; if (sym.Namespace == null) { ilg.EmitNull(); } else { ilg.EmitString(sym.Namespace); } ilg.EmitString(sym.Name); ilg.EmitCall(Compiler.Method_Symbol_intern2); } else if (value is Keyword) { Keyword keyword = (Keyword)value; if (keyword.Namespace == null) { ilg.EmitNull(); } else { ilg.EmitString(keyword.Namespace); } ilg.EmitString(keyword.Name); ilg.EmitCall(Compiler.Method_RT_keyword); } else if (value is Var) { Var var = (Var)value; ilg.EmitString(var.Namespace.Name.ToString()); ilg.EmitString(var.Symbol.Name.ToString()); ilg.EmitCall(Compiler.Method_RT_var2); } else if (value is IType) { IPersistentVector fields = (IPersistentVector)Reflector.InvokeStaticMethod(value.GetType(), "getBasis", Type.EmptyTypes); for (ISeq s = RT.seq(fields); s != null; s = s.next()) { Symbol field = (Symbol)s.first(); Type k = Compiler.TagType(Compiler.TagOf(field)); object val = Reflector.GetInstanceFieldOrProperty(value, field.Name); EmitValue(val, ilg); if (k.IsPrimitive) { ilg.Emit(OpCodes.Castclass, k); } } ConstructorInfo cinfo = value.GetType().GetConstructors()[0]; ilg.EmitNew(cinfo); } else if (value is IRecord) { //MethodInfo[] minfos = value.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public); EmitValue(PersistentArrayMap.create((IDictionary)value), ilg); MethodInfo createMI = value.GetType().GetMethod("create", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { typeof(IPersistentMap) }, null); ilg.EmitCall(createMI); } else if (value is IPersistentMap) { IPersistentMap map = (IPersistentMap)value; List <object> entries = new List <object>(map.count() * 2); foreach (IMapEntry entry in map) { entries.Add(entry.key()); entries.Add(entry.val()); } EmitListAsObjectArray(entries, ilg); ilg.EmitCall(Compiler.Method_RT_map); } else if (value is IPersistentVector) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_RT_vector); } else if (value is PersistentHashSet) { ISeq vs = RT.seq(value); if (vs == null) { ilg.EmitFieldGet(Compiler.Method_PersistentHashSet_EMPTY); } else { EmitListAsObjectArray(vs, ilg); ilg.EmitCall(Compiler.Method_PersistentHashSet_create); } } else if (value is ISeq || value is IPersistentList) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_PersistentList_create); } else if (value is Regex) { ilg.EmitString(((Regex)value).ToString()); ilg.EmitNew(Compiler.Ctor_Regex_1); } else { string cs = null; try { cs = RT.printString(value); } catch (Exception) { throw new InvalidOperationException(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", value)); } if (cs.Length == 0) { throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + value)); } if (cs.StartsWith("#<")) { throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + cs)); } ilg.EmitString(cs); ilg.EmitCall(Compiler.Method_RT_readString); partial = false; } if (partial) { if (value is IObj && RT.count(((IObj)value).meta()) > 0) { ilg.Emit(OpCodes.Castclass, typeof(IObj)); Object m = ((IObj)value).meta(); EmitValue(Compiler.ElideMeta(m), ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.Emit(OpCodes.Callvirt, Compiler.Method_IObj_withMeta); } } }
static public void EmitDynamicCallPreamble(DynamicExpression dyn, IPersistentMap spanMap, string methodName, Type returnType, IList <ParameterExpression> paramExprs, Type[] paramTypes, CljILGen ilg, out LambdaExpression lambda, out Type delType, out MethodBuilder mbLambda) { Expression call = dyn; GenContext context = Compiler.CompilerContextVar.deref() as GenContext; DynInitHelper.SiteInfo siteInfo; if (context != null && context.DynInitHelper != null) { call = context.DynInitHelper.ReduceDyn(dyn, out siteInfo); } else { throw new InvalidOperationException("Don't know how to handle callsite in this case"); } if (returnType == typeof(void)) { call = Expression.Block(call, Expression.Default(typeof(object))); returnType = typeof(object); } else if (returnType != call.Type) { call = Expression.Convert(call, returnType); } call = GenContext.AddDebugInfo(call, spanMap); delType = Microsoft.Scripting.Generation.Snippets.Shared.DefineDelegate("__interop__", returnType, paramTypes); lambda = Expression.Lambda(delType, call, paramExprs); mbLambda = null; if (context == null) { // light compile Delegate d = lambda.Compile(); int key = RT.nextID(); CacheDelegate(key, d); ilg.EmitInt(key); ilg.Emit(OpCodes.Call, Method_MethodExpr_GetDelegate); ilg.Emit(OpCodes.Castclass, delType); } else { mbLambda = context.TB.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, returnType, paramTypes); //lambda.CompileToMethod(mbLambda); // Now we get to do all this code create by hand. // the primary code is // (loc1 = fb).Target.Invoke(loc1,*args); // if return type if void, pop the value and push a null // if return type does not match the call site, add a conversion CljILGen ilg2 = new CljILGen(mbLambda.GetILGenerator()); ilg2.EmitFieldGet(siteInfo.FieldBuilder); ilg2.Emit(OpCodes.Dup); LocalBuilder siteVar = ilg2.DeclareLocal(siteInfo.DelegateType); ilg2.Emit(OpCodes.Stloc, siteVar); ilg2.EmitFieldGet(siteInfo.SiteType.GetField("Target")); ilg2.Emit(OpCodes.Ldloc, siteVar); for (int i = 0; i < paramExprs.Count; i++) { ilg2.EmitLoadArg(i); } ilg2.EmitCall(siteInfo.DelegateType.GetMethod("Invoke")); if (returnType == typeof(void)) { ilg2.Emit(OpCodes.Pop); ilg2.EmitNull(); } else if (returnType != call.Type) { EmitConvertToType(ilg2, call.Type, returnType, false); } ilg2.Emit(OpCodes.Ret); /* * return Expression.Block( * new[] { site }, * Expression.Call( * Expression.Field( * Expression.Assign(site, access), * cs.GetType().GetField("Target") * ), * node.DelegateType.GetMethod("Invoke"), * ClrExtensions.ArrayInsert(site, node.Arguments) * ) */ } }