void EmitSwapThunk(TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod("swapThunk", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(void), new Type[] { typeof(int), typeof(ILookupThunk) }); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label endLabel = ilg.DefineLabel(); Label[] labels = new Label[KeywordCallsites.count()]; for (int i = 0; i < KeywordCallsites.count(); i++) { labels[i] = ilg.DefineLabel(); } ilg.EmitLoadArg(1); ilg.Emit(OpCodes.Switch, labels); ilg.Emit(OpCodes.Br, endLabel); for (int i = 0; i < KeywordCallsites.count(); i++) { ilg.MarkLabel(labels[i]); ilg.EmitLoadArg(2); ilg.EmitFieldSet(_thunkFields[i]); ilg.Emit(OpCodes.Br, endLabel); } ilg.MarkLabel(endLabel); ilg.Emit(OpCodes.Ret); }
protected override void EmitSet(CljILGen ilg) { if (_tinfo.IsInitOnly) { throw new InvalidOperationException(String.Format("Attempt to set readonly field {0} in class {1}", _tinfo.Name, _tinfo.DeclaringType)); } ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldSet(_tinfo); }
public override void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val) { GenContext.EmitDebugInfo(ilg, _spanMap); val.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Dup); HostExpr.EmitUnboxArg(objx, ilg, FieldType); ilg.EmitFieldSet(_tinfo); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
private ConstructorBuilder EmitConstructorForNonDefType(TypeBuilder fnTB, Type baseType) { ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes()); CljILGen gen = new CljILGen(cb.GetILGenerator()); GenContext.EmitDebugInfo(gen, SpanMap); //Call base constructor ConstructorInfo baseCtorInfo = baseType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null); if (baseCtorInfo == null) { throw new InvalidOperationException("Unable to find default constructor for " + baseType.FullName); } gen.EmitLoadArg(0); gen.Emit(OpCodes.Call, baseCtorInfo); // Store Meta if (SupportsMeta) { gen.EmitLoadArg(0); gen.EmitLoadArg(1); gen.Emit(OpCodes.Castclass, typeof(IPersistentMap)); gen.EmitFieldSet(MetaField); } // store closed-overs in their fields int a = 0; int offset = !SupportsMeta ? 1 : 2; for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++) { //LocalBinding lb = (LocalBinding)s.first(); FieldBuilder fb = ClosedOverFields[a]; bool isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitLoadArg(a + offset); // gen.Emit(OpCodes.Ldarg, a + 1); gen.MaybeEmitVolatileOp(isVolatile); gen.Emit(OpCodes.Stfld, fb); } gen.Emit(OpCodes.Ret); return(cb); }
public override void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val) { if (_tinfo.IsInitOnly) { throw new InvalidOperationException(String.Format("Attempt to set readonly static field {0} in class {1}", _tinfo.Name, _tinfo.DeclaringType)); } GenContext.EmitDebugInfo(ilg, _spanMap); val.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Dup); HostExpr.EmitUnboxArg(objx, ilg, FieldType); ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldSet(_tinfo); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
void EmitSwapThunk(TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod("swapThunk", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(void), new Type[] { typeof(int), typeof(ILookupThunk) }); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label endLabel = ilg.DefineLabel(); Label[] labels = new Label[KeywordCallsites.count()]; for (int i = 0; i < KeywordCallsites.count(); i++) labels[i] = ilg.DefineLabel(); ilg.EmitLoadArg(1); ilg.Emit(OpCodes.Switch, labels); ilg.Emit(OpCodes.Br, endLabel); for (int i = 0; i < KeywordCallsites.count(); i++) { ilg.MarkLabel(labels[i]); ilg.EmitLoadArg(2); ilg.EmitFieldSet(_thunkFields[i]); ilg.Emit(OpCodes.Br, endLabel); } ilg.MarkLabel(endLabel); ilg.Emit(OpCodes.Ret); }
private ConstructorBuilder EmitConstructor(TypeBuilder fnTB, Type baseType) { ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes()); CljILGen gen = new CljILGen(cb.GetILGenerator()); GenContext.EmitDebugInfo(gen, SpanMap); //Call base constructor ConstructorInfo baseCtorInfo = baseType.GetConstructor(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public,null,Type.EmptyTypes,null); if (baseCtorInfo == null) throw new InvalidOperationException("Unable to find default constructor for " + baseType.FullName); gen.EmitLoadArg(0); gen.Emit(OpCodes.Call, baseCtorInfo); // Store Meta if (SupportsMeta) { gen.EmitLoadArg(0); gen.EmitLoadArg(1); gen.Emit(OpCodes.Castclass, typeof(IPersistentMap)); gen.EmitFieldSet(_metaField); } // store closed-overs in their fields int a = 0; int offset = !SupportsMeta ? 1 : 2; for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++) { //LocalBinding lb = (LocalBinding)s.first(); FieldBuilder fb = _closedOverFields[a]; bool isVolatile = IsVolatile(_closedOverFieldsToBindingsMap[fb]); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitLoadArg(a + offset); // gen.Emit(OpCodes.Ldarg, a + 1); gen.MaybeEmitVolatileOp(isVolatile); gen.Emit(OpCodes.Stfld, fb); } gen.Emit(OpCodes.Ret); return cb; }
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); }
private static FieldBuilder AddIProxyMethods(TypeBuilder proxyTB) { FieldBuilder fb = proxyTB.DefineField( _methodMapFieldName, typeof(IPersistentMap), FieldAttributes.Private); MethodBuilder initMb = proxyTB.DefineMethod( "__initClojureFnMappings", MethodAttributes.Public|MethodAttributes.Virtual|MethodAttributes.HideBySig, typeof(void), new Type[] { typeof(IPersistentMap) }); CljILGen gen = new CljILGen(initMb.GetILGenerator()); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitLoadArg(1); // gen.Emit(OpCodes.Ldarg_1); gen.EmitFieldSet(fb); // gen.Emit(OpCodes.Stfld, fb); gen.Emit(OpCodes.Ret); MethodBuilder updateTB = proxyTB.DefineMethod( "__updateClojureFnMappings", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(void), new Type[] { typeof(IPersistentMap) }); gen = new CljILGen(updateTB.GetILGenerator()); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Dup); gen.EmitFieldGet(fb); // gen.Emit(OpCodes.Ldfld, fb); gen.Emit(OpCodes.Castclass, typeof(IPersistentMap)); gen.EmitLoadArg(1); // gen.Emit(OpCodes.Ldarg_1); gen.EmitCall(Method_IPersistentMap_Cons); //gen.Emit(OpCodes.Call, Method_IPersistentCollection_Cons); gen.EmitFieldSet(fb); // gen.Emit(OpCodes.Stfld, fb); gen.Emit(OpCodes.Ret); MethodBuilder getMb = proxyTB.DefineMethod( "__getClojureFnMappings", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(IPersistentMap), Type.EmptyTypes); gen = new CljILGen(getMb.GetILGenerator()); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitFieldGet(fb); // gen.Emit(OpCodes.Ldfld, fb); gen.Emit(OpCodes.Ret); return fb; }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Label endLabel = ilg.DefineLabel(); Label faultLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, _spanMap); LocalBuilder thunkLoc = ilg.DeclareLocal(typeof(ILookupThunk)); LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object)); LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(thunkLoc, "thunk"); GenContext.SetLocalName(targetLoc, "target"); GenContext.SetLocalName(resultLoc, "result"); // TODO: Debug info // pseudo-code: // ILookupThunk thunk = objclass.ThunkField(i) // object target = ...code... // object val = thunk.get(target) // if ( val != thunk ) // return val // else // KeywordLookupSite site = objclass.SiteField(i) // thunk = site.fault(target) // objclass.ThunkField(i) = thunk // val = thunk.get(target) // return val ilg.EmitFieldGet(objx.ThunkField(_siteIndex)); // thunk ilg.Emit(OpCodes.Stloc, thunkLoc); // (thunkLoc <= thunk) _target.Emit(RHC.Expression, objx, ilg); // target ilg.Emit(OpCodes.Stloc, targetLoc); // (targetLoc <= target) ilg.Emit(OpCodes.Ldloc, thunkLoc); ilg.Emit(OpCodes.Ldloc, targetLoc); ilg.EmitCall(Compiler.Method_ILookupThunk_get); // result ilg.Emit(OpCodes.Stloc, resultLoc); // (resultLoc <= result) ilg.Emit(OpCodes.Ldloc, thunkLoc); ilg.Emit(OpCodes.Ldloc, resultLoc); ilg.Emit(OpCodes.Beq, faultLabel); ilg.Emit(OpCodes.Ldloc, resultLoc); // result ilg.Emit(OpCodes.Br, endLabel); ilg.MarkLabel(faultLabel); ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex)); // site ilg.Emit(OpCodes.Ldloc, targetLoc); // site, target ilg.EmitCall(Compiler.Method_ILookupSite_fault); // new-thunk ilg.Emit(OpCodes.Dup); // new-thunk, new-thunk ilg.EmitFieldSet(objx.ThunkField(_siteIndex)); // new-thunk ilg.Emit(OpCodes.Ldloc, targetLoc); // new-thunk, target ilg.EmitCall(Compiler.Method_ILookupThunk_get); // result ilg.MarkLabel(endLabel); // result 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); } } }
protected override void EmitSet(CljILGen ilg) { ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldSet(_tinfo); }
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); }
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); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { if (objx.FnMode == FnMode.Light) { // This will emit a plain Keyword reference, rather than a callsite. InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target)); ie.Emit(rhc, objx, ilg); } else { Label endLabel = ilg.DefineLabel(); Label faultLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, _spanMap); LocalBuilder thunkLoc = ilg.DeclareLocal(typeof(ILookupThunk)); LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object)); LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(thunkLoc, "thunk"); GenContext.SetLocalName(targetLoc, "target"); GenContext.SetLocalName(resultLoc, "result"); // TODO: Debug info // pseudo-code: // ILookupThunk thunk = objclass.ThunkField(i) // object target = ...code... // object val = thunk.get(target) // if ( val != thunk ) // return val // else // KeywordLookupSite site = objclass.SiteField(i) // thunk = site.fault(target) // objclass.ThunkField(i) = thunk // val = thunk.get(target) // return val ilg.EmitFieldGet(objx.ThunkField(_siteIndex)); // thunk ilg.Emit(OpCodes.Stloc, thunkLoc); // (thunkLoc <= thunk) _target.Emit(RHC.Expression, objx, ilg); // target ilg.Emit(OpCodes.Stloc, targetLoc); // (targetLoc <= target) ilg.Emit(OpCodes.Ldloc, thunkLoc); ilg.Emit(OpCodes.Ldloc, targetLoc); ilg.EmitCall(Compiler.Method_ILookupThunk_get); // result ilg.Emit(OpCodes.Stloc, resultLoc); // (resultLoc <= result) ilg.Emit(OpCodes.Ldloc, thunkLoc); ilg.Emit(OpCodes.Ldloc, resultLoc); ilg.Emit(OpCodes.Beq, faultLabel); ilg.Emit(OpCodes.Ldloc, resultLoc); // result ilg.Emit(OpCodes.Br, endLabel); ilg.MarkLabel(faultLabel); ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex)); // site ilg.Emit(OpCodes.Ldloc, targetLoc); // site, target ilg.EmitCall(Compiler.Method_ILookupSite_fault); // new-thunk ilg.Emit(OpCodes.Dup); // new-thunk, new-thunk ilg.EmitFieldSet(objx.ThunkField(_siteIndex)); // new-thunk ilg.Emit(OpCodes.Ldloc, targetLoc); // new-thunk, target ilg.EmitCall(Compiler.Method_ILookupThunk_get); // result ilg.MarkLabel(endLabel); // result if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); } }
private static void EmitExposers(TypeBuilder proxyTB, Type superClass, IPersistentMap exposesFields) { for ( ISeq s = RT.seq(exposesFields); s != null; s = s.next() ) { IMapEntry me = (IMapEntry)s.first(); Symbol protectedFieldSym = (Symbol)me.key(); IPersistentMap accessMap = (IPersistentMap)me.val(); string fieldName = protectedFieldSym.Name; Symbol getterSym = (Symbol)accessMap.valAt(_getKw, null); Symbol setterSym = (Symbol)accessMap.valAt(_setKW, null); FieldInfo fld = null; if ( getterSym != null || setterSym != null ) fld = superClass.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Instance); if (getterSym != null) { MethodAttributes attribs = MethodAttributes.Public; if (fld.IsStatic) attribs |= MethodAttributes.Static; MethodBuilder mb = proxyTB.DefineMethod(getterSym.Name, attribs, fld.FieldType, Type.EmptyTypes); CljILGen gen = new CljILGen(mb.GetILGenerator()); //if (fld.IsStatic) // gen.Emit(OpCodes.Ldsfld, fld); //else //{ // gen.Emit(OpCodes.Ldarg_0); // gen.Emit(OpCodes.Ldfld, fld); //} if (!fld.IsStatic) gen.EmitLoadArg(0); gen.MaybeEmitVolatileOp(fld); gen.EmitFieldGet(fld); gen.Emit(OpCodes.Ret); } if (setterSym != null) { MethodAttributes attribs = MethodAttributes.Public; if (fld.IsStatic) attribs |= MethodAttributes.Static; MethodBuilder mb = proxyTB.DefineMethod(setterSym.Name, attribs, typeof(void), new Type[] { fld.FieldType }); CljILGen gen = new CljILGen(mb.GetILGenerator()); if (fld.IsStatic) { gen.Emit(OpCodes.Ldarg_0); //gen.Emit(OpCodes.Stsfld, fld); } else { gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldarg_1); //gen.Emit(OpCodes.Stfld, fld); } gen.MaybeEmitVolatileOp(fld); gen.EmitFieldSet(fld); gen.Emit(OpCodes.Ret); } } }
protected override void EmitSet(CljILGen ilg) { ilg.EmitFieldSet(_tinfo); }