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 CreateStaticCtor() { //Console.WriteLine("Creating static ctor for {0}", // _typeBuilder.AssemblyQualifiedName); ConstructorBuilder ctorB = _typeBuilder.DefineConstructor(MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); CljILGen gen = new CljILGen(ctorB.GetILGenerator()); for (int i = 0; i < _fieldBuilders.Count; i++) { FieldBuilder fb = _fieldBuilders[i]; Expression fbInit = _fieldInits[i]; string setterName = String.Format("{0}_setter", fb.Name); MethodBuilder mbSetter = _typeBuilder.DefineMethod( setterName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, fbInit.Type, Type.EmptyTypes); LambdaExpression initL = Expression.Lambda(Expression.Assign(Expression.Field(null, fb), fbInit)); initL.CompileToMethod(mbSetter); gen.EmitCall(mbSetter); gen.Emit(OpCodes.Pop); } gen.Emit(OpCodes.Ret); }
private void EmitLoadNsInitForDeftype(CljILGen ilg) { string nsname = ((Symbol)RT.second(Src)).Namespace; if ( !nsname.Equals("clojure.core")) { ilg.EmitString("clojure.core"); ilg.EmitString("require"); ilg.EmitCall(Compiler.Method_RT_var2); ilg.EmitCall(Compiler.Method_Var_getRawRoot); ilg.Emit(OpCodes.Castclass, typeof(IFn)); ilg.EmitNull(); ilg.EmitString(nsname); ilg.EmitCall(Compiler.Method_Symbol_intern2); ilg.EmitCall(Compiler.Methods_IFn_invoke[1]); ilg.Emit(OpCodes.Pop); } }
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) { _expr.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IObj)); _meta.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.EmitCall(Compiler.Method_IObj_withMeta); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { MethodExpr.EmitArgsAsArray(_keyvals, objx, ilg); ilg.EmitCall(Compiler.Method_RT_map); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { _expr.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IObj)); _meta.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.EmitCall(Compiler.Method_IObj_withMeta); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
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); } } }
void CreateStaticCtor() { ConstructorBuilder ctorB = _typeBuilder.DefineConstructor(MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); CljILGen gen = new CljILGen(ctorB.GetILGenerator()); foreach (SiteInfo si in _siteInfos) { string setterName = String.Format("{0}_setter", si.FieldBuilder.Name); MethodBuilder mbSetter = _typeBuilder.DefineMethod( setterName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, si.SiteType, Type.EmptyTypes); //LambdaExpression initL = Expression.Lambda(Expression.Assign(Expression.Field(null, fb), fbInit)); //initL.CompileToMethod(mbSetter); CljILGen setterIlg = new CljILGen(mbSetter.GetILGenerator()); if (!(si.Binder is IClojureBinder b)) { throw new InvalidOperationException("Binder of unknown type"); } b.GenerateCreationIL(mbSetter.GetILGenerator()); setterIlg.EmitCall(si.SiteType.GetMethod("Create")); setterIlg.Emit(OpCodes.Dup); LocalBuilder v0 = setterIlg.DeclareLocal(typeof(Object)); setterIlg.Emit(OpCodes.Stloc, v0); setterIlg.Emit(OpCodes.Stsfld, si.FieldBuilder); setterIlg.Emit(OpCodes.Ldloc, v0); setterIlg.Emit(OpCodes.Ret); gen.EmitCall(mbSetter); gen.Emit(OpCodes.Pop); } gen.Emit(OpCodes.Ret); }
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); } } }
static void EmitMain(GenContext context, TypeBuilder proxyTB, string mainName, FieldBuilder mainFB) { MethodBuilder cb = proxyTB.DefineMethod("Main",MethodAttributes.Public| MethodAttributes.Static,CallingConventions.Standard,typeof(void),new Type[] { typeof(String[]) }); CljILGen gen = new CljILGen(cb.GetILGenerator()); ; Label noMainLabel = gen.DefineLabel(); Label endLabel = gen.DefineLabel(); EmitGetVar(gen, mainFB); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, noMainLabel); gen.Emit(OpCodes.Castclass, typeof(IFn)); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitCall(Method_RT_seq); // gen.Emit(OpCodes.Call, Method_RT_seq); gen.EmitCall(Method_IFn_applyTo_Object_ISeq); // gen.Emit(OpCodes.Call, Method_IFn_applyTo_Object_ISeq); gen.Emit(OpCodes.Pop); gen.Emit(OpCodes.Br_S, endLabel); // no main found gen.MarkLabel(noMainLabel); EmitUnsupported(gen, mainName); gen.MarkLabel(endLabel); gen.Emit(OpCodes.Ret); //context.AssyBldr.SetEntryPoint(cb); context.AssemblyBuilder.SetEntryPoint(cb); }
static void EmitGetVar(CljILGen gen, FieldBuilder fb) { Label falseLabel = gen.DefineLabel(); Label endLabel = gen.DefineLabel(); gen.EmitFieldGet(fb); // gen.Emit(OpCodes.Ldsfld,fb); gen.Emit(OpCodes.Dup); gen.EmitCall(Method_Var_isBound); // gen.Emit(OpCodes.Call, Method_Var_IsBound); gen.Emit(OpCodes.Brfalse_S,falseLabel); gen.Emit(OpCodes.Call,Method_Var_get); gen.Emit(OpCodes.Br_S,endLabel); gen.MarkLabel(falseLabel); gen.Emit(OpCodes.Pop); gen.EmitNull(); // gen.Emit(OpCodes.Ldnull); gen.MarkLabel(endLabel); }
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); } }
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) { Label?loopLabel = (Label)Compiler.LoopLabelVar.deref(); if (loopLabel == null) { throw new InvalidOperationException("Recur not in proper context."); } { for (int i = 0; i < _loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Expr arg = (Expr)_args.nth(i); Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mpeArg = arg as MaybePrimitiveExpr; Type pt = Compiler.MaybePrimitiveType(arg); if (pt == primt) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); } else if (primt == typeof(long) && pt == typeof(int)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_I8); } else if (primt == typeof(double) && pt == typeof(float)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R8); } else if (primt == typeof(int) && pt == typeof(long)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.EmitCall(Compiler.Method_RT_intCast_long); } else if (primt == typeof(float) && pt == typeof(double)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R4); } else { throw new ArgumentException(String.Format( "{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}", _source, _spanMap != null ? (int)_spanMap.valAt(RT.StartLineKey, 0) : 0, lb.Name, (arg.HasClrType ? arg.ClrType.Name : "Object"), primt.Name)); } } else { arg.Emit(RHC.Expression, objx, ilg); } } } for (int i = _loopLocals.count() - 1; i >= 0; i--) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); //Type primt = lb.PrimitiveType; if (lb.IsArg) { //ilg.Emit(OpCodes.Starg, lb.Index - (objx.IsStatic ? 0 : 1)); ilg.EmitStoreArg(lb.Index); } else { ilg.Emit(OpCodes.Stloc, lb.LocalVar); } } ilg.Emit(OpCodes.Br, loopLabel.Value); }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { _target.Emit(RHC.Expression, objx, ilg); ilg.EmitCall(Compiler.Method_Monitor_Enter); Compiler.NilExprInstance.Emit(rhc, objx, ilg); }
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; }
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); } } }
private void EmitLoadNsInitForDeftype(CljILGen ilg) { string nsname = ((Symbol)RT.second(_src)).Namespace; if ( !nsname.Equals("clojure.core")) { ilg.EmitString("clojure.core"); ilg.EmitString("require"); ilg.EmitCall(Compiler.Method_RT_var2); ilg.EmitCall(Compiler.Method_Var_getRawRoot); ilg.Emit(OpCodes.Castclass, typeof(IFn)); ilg.EmitNull(); ilg.EmitString(nsname); ilg.EmitCall(Compiler.Method_Symbol_intern2); ilg.EmitCall(Compiler.Methods_IFn_invoke[1]); ilg.Emit(OpCodes.Pop); } }
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); } }
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); }
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 override void EmitStatics(TypeBuilder tb) { if (IsDefType) { // getBasis() { MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes); CljILGen ilg = new CljILGen(mbg.GetILGenerator()); EmitValue(HintedFields, ilg); ilg.Emit(OpCodes.Ret); } if (Fields.count() > HintedFields.count()) { // create(IPersistentMap) MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) }); CljILGen gen = new CljILGen(mbc.GetILGenerator()); LocalBuilder kwLocal = gen.DeclareLocal(typeof(Keyword)); List<LocalBuilder> locals = new List<LocalBuilder>(); for (ISeq s = RT.seq(HintedFields); s != null; s = s.next()) { string bName = ((Symbol)s.first()).Name; Type t = Compiler.TagType(Compiler.TagOf(s.first())); // local_kw = Keyword.intern(bname) // local_i = arg_0.valAt(kw,null) gen.EmitLoadArg(0); gen.EmitString(bName); gen.EmitCall(Compiler.Method_Keyword_intern_string); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Stloc, kwLocal.LocalIndex); gen.EmitNull(); gen.EmitCall(Compiler.Method_IPersistentMap_valAt2); LocalBuilder lb = gen.DeclareLocal(t); locals.Add(lb); if (t.IsPrimitive) gen.EmitUnbox(t); gen.Emit(OpCodes.Stloc, lb.LocalIndex); // arg_0 = arg_0.without(local_kw); gen.EmitLoadArg(0); gen.Emit(OpCodes.Ldloc, kwLocal.LocalIndex); gen.EmitCall(Compiler.Method_IPersistentMap_without); gen.EmitStoreArg(0); } foreach (LocalBuilder lb in locals) gen.Emit(OpCodes.Ldloc, lb.LocalIndex); gen.EmitNull(); gen.EmitLoadArg(0); gen.EmitCall(Compiler.Method_RT_seqOrElse); gen.EmitNew(CtorInfo); gen.Emit(OpCodes.Ret); } } }
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); }
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); } }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { _target.Emit(RHC.Expression, objx, ilg); ilg.EmitCall(Compiler.Method_Monitor_Exit); Compiler.NilExprInstance.Emit(rhc, objx, ilg); }
private static void GenerateProxyMethod( TypeBuilder proxyTB, FieldBuilder mapField, MethodInfo m, HashSet<MethodBuilder> specialMethods) { MethodAttributes attribs = m.Attributes; bool callBaseMethod; if ( (attribs & MethodAttributes.Abstract) == MethodAttributes.Abstract ) { attribs &= ~MethodAttributes.Abstract; callBaseMethod = false; } else { callBaseMethod = true; } attribs &= ~MethodAttributes.NewSlot; attribs |= MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Public; //Console.Write("Generating proxy method {0}(", m.Name); //foreach (ParameterInfo p in m.GetParameters()) // Console.Write("{0}, ", p.ParameterType.FullName); //Console.Write(") "); //Console.WriteLine(attribs.ToString()); MethodBuilder proxym = proxyTB.DefineMethod( m.Name, attribs, m.CallingConvention, m.ReturnType, m.GetParameters().Select<ParameterInfo, Type>(p => p.ParameterType).ToArray<Type>()); if (m.IsSpecialName) specialMethods.Add(proxym); CljILGen gen = new CljILGen(proxym.GetILGenerator()); Label elseLabel = gen.DefineLabel(); Label endLabel = gen.DefineLabel(); //// Print a little message, for debugging purposes //gen.Emit(OpCodes.Ldstr, String.Format("Calling {0} / {1}", proxyTB.FullName, m.ToString())); //gen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", // new Type[] { typeof(string) })); //gen.Emit(OpCodes.Call, typeof(Console).GetMethod("get_Out")); //gen.Emit(OpCodes.Call, typeof(System.IO.TextWriter).GetMethod("Flush")); // Lookup method name in map gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitFieldGet(mapField); // gen.Emit(OpCodes.Ldfld, mapField); gen.EmitString(m.Name); // gen.Emit(OpCodes.Ldstr, m.Name); gen.EmitCall(Method_RT_get); // gen.Emit(OpCodes.Call, Method_RT_get); gen.Emit(OpCodes.Dup); gen.EmitNull(); // gen.Emit(OpCodes.Ldnull); gen.Emit(OpCodes.Beq_S, elseLabel); // map entry found ParameterInfo[] pinfos = m.GetParameters(); gen.Emit(OpCodes.Castclass, typeof(IFn)); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); // push implicit 'this' arg. for (int i = 0; i < pinfos.Length; i++) { gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (m.GetParameters()[i].ParameterType.IsValueType) gen.Emit(OpCodes.Box,pinfos[i].ParameterType); } int parmCount = pinfos.Length; gen.EmitCall(GetIFnInvokeMethodInfo(parmCount+1)); // gen.Emit(OpCodes.Call, GetIFnInvokeMethodInfo(parmCount + 1)); if (m.ReturnType == typeof(void)) gen.Emit(OpCodes.Pop); else gen.Emit(OpCodes.Unbox_Any, m.ReturnType); gen.Emit(OpCodes.Br_S,endLabel); // map entry not found gen.MarkLabel(elseLabel); gen.Emit(OpCodes.Pop); // get rid of null leftover from the 'get' if ( callBaseMethod ) { gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < parmCount; i++) gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); gen.Emit(OpCodes.Call, m); // gen.EmitCall(m) improperly emits a callvirt in some cases } else { gen.EmitString(m.Name); // gen.Emit(OpCodes.Ldstr, m.Name); gen.EmitNew(CtorInfo_NotImplementedException_1); // gen.Emit(OpCodes.Newobj, CtorInfo_NotImplementedException_1); gen.Emit(OpCodes.Throw); } gen.MarkLabel(endLabel); gen.Emit(OpCodes.Ret); }
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); }
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 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); } } }
/// <summary> /// Set up Var fields and (maybe) load assembly for the namespace. /// </summary> /// <param name="proxyTB"></param> /// <param name="varMap"></param> /// <param name="loadImplNameSpace"></param> /// <param name="implNamespace"></param> private static void DefineStaticCtor(TypeBuilder proxyTB, string prefix, Dictionary<string, FieldBuilder> varMap, bool loadImplNameSpace, string implNamespace, string implCname) { ConstructorBuilder cb = proxyTB.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard,Type.EmptyTypes); CljILGen gen = new CljILGen(cb.GetILGenerator()); foreach (KeyValuePair<string, FieldBuilder> pair in varMap) { gen.EmitString(implNamespace); // gen.Emit(OpCodes.Ldstr, implNamespace); gen.EmitString(prefix + pair.Key); // gen.Emit(OpCodes.Ldstr, prefix + pair.Key); gen.EmitCall(Method_Var_internPrivate); // gen.Emit(OpCodes.Call, Method_Var_internPrivate); gen.Emit(OpCodes.Stsfld, pair.Value); } if (loadImplNameSpace) { gen.EmitString("clojure.core"); // gen.Emit(OpCodes.Ldstr, "clojure.core"); gen.EmitString("load"); // gen.Emit(OpCodes.Ldstr, "load"); gen.EmitCall(Method_RT_var2); // gen.Emit(OpCodes.Call, Method_RT_var2); gen.EmitString("/" + implCname); // gen.Emit(OpCodes.Ldstr, "/" + implCname); gen.EmitCall(Compiler.Methods_IFn_invoke[1]); // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[1]); gen.Emit(OpCodes.Pop); } gen.Emit(OpCodes.Ret); }
private static void EmitForwardingMethod(TypeBuilder proxyTB, bool isStatic, FieldBuilder regularFB, FieldBuilder overloadFB, MethodSignature sig, ElseGenDelegate elseGen) { MethodAttributes attributes; CallingConventions conventions; if (isStatic) { attributes = MethodAttributes.Public | MethodAttributes.Static; conventions = CallingConventions.Standard; } else { attributes = MethodAttributes.Public | MethodAttributes.Virtual; conventions = CallingConventions.HasThis; } MethodBuilder mb = proxyTB.DefineMethod(sig.Name, attributes, conventions, sig.ReturnType, sig.ParamTypes); CljILGen gen = new CljILGen(mb.GetILGenerator()); Label foundLabel = gen.DefineLabel(); Label elseLabel = gen.DefineLabel(); Label endLabel = gen.DefineLabel(); if (sig.ParamTypes.Length > 18) elseGen(gen); else { if (overloadFB != null) { EmitGetVar(gen, overloadFB); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brtrue_S, foundLabel); gen.Emit(OpCodes.Pop); } EmitGetVar(gen, regularFB); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, elseLabel); if (overloadFB != null) gen.MarkLabel(foundLabel); gen.Emit(OpCodes.Castclass, typeof(IFn)); if (!isStatic) gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < sig.ParamTypes.Length; i++) { gen.EmitLoadArg(isStatic ? i : i + 1); // gen.Emit(OpCodes.Ldarg, i + 1); if (sig.ParamTypes[i].IsValueType) gen.Emit(OpCodes.Box, sig.ParamTypes[i]); } gen.EmitCall(Compiler.Methods_IFn_invoke[sig.ParamTypes.Length + (isStatic ? 0 : 1)]); //gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[sig.ParamTypes.Length + (isStatic ? 0 : 1)]); if (sig.ReturnType == typeof(void)) gen.Emit(OpCodes.Pop); else if (sig.ReturnType.IsValueType) gen.Emit(OpCodes.Unbox_Any,sig.ReturnType); gen.Emit(OpCodes.Br_S, endLabel); gen.MarkLabel(elseLabel); gen.Emit(OpCodes.Pop); elseGen(gen); gen.MarkLabel(endLabel); gen.Emit(OpCodes.Ret); } }
protected override void EmitStatics(TypeBuilder tb) { if (IsDefType) { // getBasis() { MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes); CljILGen ilg = new CljILGen(mbg.GetILGenerator()); EmitValue(HintedFields, ilg); ilg.Emit(OpCodes.Ret); } if (Fields.count() > HintedFields.count()) { // create(IPersistentMap) MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) }); CljILGen gen = new CljILGen(mbc.GetILGenerator()); LocalBuilder kwLocal = gen.DeclareLocal(typeof(Keyword)); List <LocalBuilder> locals = new List <LocalBuilder>(); for (ISeq s = RT.seq(HintedFields); s != null; s = s.next()) { string bName = ((Symbol)s.first()).Name; Type t = Compiler.TagType(Compiler.TagOf(s.first())); // local_kw = Keyword.intern(bname) // local_i = arg_0.valAt(kw,null) gen.EmitLoadArg(0); gen.EmitString(bName); gen.EmitCall(Compiler.Method_Keyword_intern_string); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Stloc, kwLocal.LocalIndex); gen.EmitNull(); gen.EmitCall(Compiler.Method_IPersistentMap_valAt2); LocalBuilder lb = gen.DeclareLocal(t); locals.Add(lb); if (t.IsPrimitive) { gen.EmitUnbox(t); } gen.Emit(OpCodes.Stloc, lb.LocalIndex); // arg_0 = arg_0.without(local_kw); gen.EmitLoadArg(0); gen.Emit(OpCodes.Ldloc, kwLocal.LocalIndex); gen.EmitCall(Compiler.Method_IPersistentMap_without); gen.EmitStoreArg(0); } foreach (LocalBuilder lb in locals) { gen.Emit(OpCodes.Ldloc, lb.LocalIndex); } gen.EmitNull(); // __meta gen.EmitLoadArg(0); // __extmap gen.EmitCall(Compiler.Method_RT_seqOrElse); gen.Emit(OpCodes.Ldc_I4_0); // __hash gen.Emit(OpCodes.Ldc_I4_0); // __hasheq gen.EmitNew(CtorInfo); gen.Emit(OpCodes.Ret); } } }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { MethodExpr.EmitArgsAsArray(_keyvals, objx, ilg); ilg.EmitCall(Compiler.Method_RT_map); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Label loopLabel = (Label)Compiler.LoopLabelVar.deref(); if (loopLabel == null) throw new InvalidOperationException("Recur not in proper context."); { for (int i = 0; i < _loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Expr arg = (Expr)_args.nth(i); Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mpeArg = arg as MaybePrimitiveExpr; Type pt = Compiler.MaybePrimitiveType(arg); if (pt == primt) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); } else if (primt == typeof(long) && pt == typeof(int)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_I8); } else if (primt == typeof(double) && pt == typeof(float)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R8); } else if (primt == typeof(int) && pt == typeof(long)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.EmitCall(Compiler.Method_RT_intCast_long); } else if (primt == typeof(float) && pt == typeof(double)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R4); } else { throw new ArgumentException(String.Format( "{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}", _source, _spanMap != null ? (int)_spanMap.valAt(RT.StartLineKey, 0) : 0, lb.Name, (arg.HasClrType ? arg.ClrType.Name : "Object"), primt.Name)); } } else { arg.Emit(RHC.Expression, objx, ilg); } } } for (int i = _loopLocals.count() - 1; i >= 0; i--) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Type primt = lb.PrimitiveType; if (lb.IsArg) //ilg.Emit(OpCodes.Starg, lb.Index - (objx.IsStatic ? 0 : 1)); ilg.EmitStoreArg(lb.Index); else { ilg.Emit(OpCodes.Stloc, lb.LocalVar); } } ilg.Emit(OpCodes.Br, loopLabel); //if (rhc != RHC.Statement) // ilg.Emit(OpCodes.Ldnull); }
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) * ) */ } }