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); }
void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { Label nullLabel = ilg.DefineLabel(); Label falseLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); Label trueLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, _sourceSpan); if (_testExpr is StaticMethodExpr sme && sme.CanEmitIntrinsicPredicate()) { sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel); }
private void DoEmit(ObjExpr fn, TypeBuilder tb) { MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; MethodBuilder mb = tb.DefineMethod(MethodName, attribs, ReturnType, ArgTypes); SetCustomAttributes(mb); CljILGen baseIlg = new CljILGen(mb.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); Body.Emit(RHC.Return, fn, baseIlg); if (Body.HasNormalExit()) { baseIlg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } if (IsExplicit) { tb.DefineMethodOverride(mb, ExplicitMethodInfo); } }
public override void Emit(ObjExpr fn, TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, ReturnType, ArgTypes); SetCustomAttributes(mb); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label loopLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, SpanMap); try { Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); ilg.MarkLabel(loopLabel); EmitBody(Objx, ilg, _retType, Body); if (Body.HasNormalExit()) { ilg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } if (IsExplicit) { tb.DefineMethodOverride(mb, ExplicitMethodInfo); } }
private void DoEmitPrimOrStatic(ObjExpr fn, TypeBuilder tb, bool isStatic) { MethodAttributes attribs = isStatic ? MethodAttributes.Static | MethodAttributes.Public : MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; string methodName = isStatic ? "invokeStatic" : "invokePrim"; MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, GetReturnType(), _argTypes); if (!isStatic) { SetCustomAttributes(baseMB); } CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); EmitBody(Objx, baseIlg, _retType, _body); if (_body.HasNormalExit()) { baseIlg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } // Generate the regular invoke, calling the static or prim method MethodBuilder regularMB = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), GetArgTypes()); SetCustomAttributes(regularMB); CljILGen regIlg = new CljILGen(regularMB.GetILGenerator()); if (!isStatic) { regIlg.Emit(OpCodes.Ldarg_0); } for (int i = 0; i < _argTypes.Length; i++) { regIlg.EmitLoadArg(i + 1); HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]); } regIlg.Emit(OpCodes.Call, baseMB); if (GetReturnType().IsValueType) { regIlg.Emit(OpCodes.Box, GetReturnType()); } regIlg.Emit(OpCodes.Ret); }
void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { List <LocalBuilder> locals = new List <LocalBuilder>(); for (int i = 0; i < _bindingInits.count(); i++) { BindingInit bi = (BindingInit)_bindingInits.nth(i); Type primType = Compiler.MaybePrimitiveType(bi.Init); if (primType != null) { LocalBuilder local = ilg.DeclareLocal(primType); locals.Add(local); GenContext.SetLocalName(local, bi.Binding.Name); bi.Binding.LocalVar = local; ((MaybePrimitiveExpr)bi.Init).EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stloc, local); } else { LocalBuilder local = ilg.DeclareLocal(typeof(Object)); locals.Add(local); GenContext.SetLocalName(local, bi.Binding.Name); bi.Binding.LocalVar = local; bi.Init.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stloc, local); } } Label loopLabel = ilg.DefineLabel(); ilg.MarkLabel(loopLabel); try { if (_isLoop) { Var.pushThreadBindings(PersistentHashMap.create(Compiler.LoopLabelVar, loopLabel)); } if (emitUnboxed) { ((MaybePrimitiveExpr)_body).EmitUnboxed(rhc, objx, ilg); } else { _body.Emit(rhc, objx, ilg); } } finally { if (_isLoop) { Var.popThreadBindings(); } } }
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); }
public virtual void Emit(ObjExpr fn, TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.Public, ReturnType, ArgTypes); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label loopLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, SpanMap); try { Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); ilg.MarkLabel(loopLabel); Body.Emit(RHC.Return, fn, ilg); ilg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } }
internal void LightEmit(ObjExpr fn, Type fnType) { if (DynMethod != null) { return; } if (Prim != null || fn.IsStatic) { throw new InvalidOperationException("No light compile allowed for static methods or methods with primitive interfaces"); } Type[] argTypes = ClrExtensions.ArrayInsert(fnType, GetArgTypes()); DynamicMethod meth = new DynamicMethod(GetMethodName(), GetReturnType(), argTypes, true); CljILGen baseIlg = new CljILGen(meth.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); //GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); _body.Emit(RHC.Return, fn, baseIlg); if (_body.HasNormalExit()) { baseIlg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } DynMethod = meth; }
public override void Emit(ObjExpr fn, TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, GetReturnType(), GetArgTypes()); SetCustomAttributes(mb); //Console.Write("Compiling method {0} ", GetMethodName()); //foreach (Type t in GetArgTypes()) // Console.Write("{0}, ", t.Name); //Console.WriteLine("returning {0}", GetReturnType().Name); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label loopLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, SpanMap); try { Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); ilg.MarkLabel(loopLabel); EmitBody(Objx, ilg, _retType, _body); if (_body.HasNormalExit()) { ilg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } if (IsExplicit) { tb.DefineMethodOverride(mb, _explicitMethodInfo); } }
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); }
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); } }
// TODO: Eliminate common code between EmitProtoLight and EmitProtoFull void EmitProtoLight(RHC rhc, ObjExpr objx, CljILGen ilg) { Label endLabel = ilg.DefineLabel(); Var v = ((VarExpr)_fexpr).Var; Expr e = (Expr)_args.nth(0); e.Emit(RHC.Expression, objx, ilg); // target LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(targetTemp, "target"); ilg.Emit(OpCodes.Stloc, targetTemp); // (targetTemp <= target) ilg.EmitString(String.Format("In Light Proto for {0}", v.Symbol.ToString())); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //if (_protocolOn != null) //{ // ilg.Emit(OpCodes.Ldloc, targetTemp); // target // ilg.Emit(OpCodes.Isinst, _protocolOn); // (target or null) // ilg.Emit(OpCodes.Ldnull); // (target or null), null // ilg.Emit(OpCodes.Cgt_Un); // (0 or 1) // ilg.Emit(OpCodes.Brtrue, onLabel); //} objx.EmitVar(ilg, v); // var ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Call, typeof(Object).GetMethod("GetType")); ilg.Emit(OpCodes.Callvirt, typeof(Object).GetMethod("ToString")); ilg.EmitString("Expected AFunction, got "); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(String) })); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) })); ilg.Emit(OpCodes.Castclass, typeof(AFunction)); ilg.EmitString("Castclass worked "); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) })); ilg.Emit(OpCodes.Ldloc, targetTemp); // proto-fn, target EmitArgsAndCall(1, rhc, objx, ilg); ilg.EmitString("gen'd args and called"); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) })); 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 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); }
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 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); }
private void DoEmitPrim(ObjExpr fn, TypeBuilder tb) { MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; string methodName = "invokePrim"; Type returnType; if (_retType == typeof(double) || _retType == typeof(long)) { returnType = ReturnType; } else { returnType = typeof(object); } MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, returnType, _argTypes); SetCustomAttributes(baseMB); CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); EmitBody(Objx, baseIlg, _retType, Body); if (Body.HasNormalExit()) { baseIlg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } // Generate the regular invoke, calling the prim method MethodBuilder regularMB = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), ArgTypes); SetCustomAttributes(regularMB); CljILGen regIlg = new CljILGen(regularMB.GetILGenerator()); regIlg.Emit(OpCodes.Ldarg_0); for (int i = 0; i < _argTypes.Length; i++) { regIlg.EmitLoadArg(i + 1); HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]); } regIlg.Emit(OpCodes.Call, baseMB); if (ReturnType.IsValueType) { regIlg.Emit(OpCodes.Box, ReturnType); } regIlg.Emit(OpCodes.Ret); }
public override void Emit(ObjExpr fn, TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, GetReturnType(), GetArgTypes()); SetCustomAttributes(mb); //Console.Write("Compiling method {0} ", GetMethodName()); //foreach (Type t in GetArgTypes()) // Console.Write("{0}, ", t.Name); //Console.WriteLine("returning {0}", GetReturnType().Name); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label loopLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, SpanMap); try { Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this)); ilg.MarkLabel(loopLabel); EmitBody(Objx,ilg,_retType,_body); if ( _body.HasNormalExit() ) ilg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } if (IsExplicit) tb.DefineMethodOverride(mb, _explicitMethodInfo); }
// TODO: Eliminate common code between EmitProtoLight and EmitProtoFull void EmitProtoLight(RHC rhc, ObjExpr objx, CljILGen ilg) { Label endLabel = ilg.DefineLabel(); Var v = ((VarExpr)_fexpr).Var; Expr e = (Expr)_args.nth(0); e.Emit(RHC.Expression, objx, ilg); // target LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(targetTemp, "target"); ilg.Emit(OpCodes.Stloc, targetTemp); // (targetTemp <= target) ilg.EmitString(String.Format("In Light Proto for {0}",v.Symbol.ToString())); ilg.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[] { typeof(string) })); //if (_protocolOn != null) //{ // ilg.Emit(OpCodes.Ldloc, targetTemp); // target // ilg.Emit(OpCodes.Isinst, _protocolOn); // (target or null) // ilg.Emit(OpCodes.Ldnull); // (target or null), null // ilg.Emit(OpCodes.Cgt_Un); // (0 or 1) // ilg.Emit(OpCodes.Brtrue, onLabel); //} objx.EmitVar(ilg, v); // var ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Call, typeof(Object).GetMethod("GetType")); ilg.Emit(OpCodes.Callvirt, typeof(Object).GetMethod("ToString")); ilg.EmitString("Expected AFunction, got "); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(String) })); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) })); ilg.Emit(OpCodes.Castclass, typeof(AFunction)); ilg.EmitString("Castclass worked "); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) })); ilg.Emit(OpCodes.Ldloc, targetTemp); // proto-fn, target EmitArgsAndCall(1, rhc, objx, ilg); ilg.EmitString("gen'd args and called"); ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) })); 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 DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { Label nullLabel = ilg.DefineLabel(); Label falseLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); Label trueLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, _sourceSpan); StaticMethodExpr sme = _testExpr as StaticMethodExpr; if (sme != null && sme.CanEmitIntrinsicPredicate()) sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel); else if (Compiler.MaybePrimitiveType(_testExpr) == typeof(bool)) { ((MaybePrimitiveExpr)_testExpr).EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Brfalse, falseLabel); } else { LocalBuilder tempLoc = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(tempLoc, "test"); _testExpr.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Stloc, tempLoc); ilg.Emit(OpCodes.Brfalse, nullLabel); ilg.Emit(OpCodes.Ldloc, tempLoc); ilg.Emit(OpCodes.Isinst, typeof(bool)); ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Cgt_Un); ilg.Emit(OpCodes.Brfalse, trueLabel); ilg.Emit(OpCodes.Ldloc, tempLoc); ilg.Emit(OpCodes.Unbox_Any, typeof(bool)); ilg.Emit(OpCodes.Ldc_I4_0); ilg.Emit(OpCodes.Ceq); ilg.Emit(OpCodes.Brtrue, falseLabel); } ilg.MarkLabel(trueLabel); if (emitUnboxed) ((MaybePrimitiveExpr)_thenExpr).EmitUnboxed(rhc, objx, ilg); else _thenExpr.Emit(rhc, objx, ilg); if ( _thenExpr.HasNormalExit() ) ilg.Emit(OpCodes.Br, endLabel); ilg.MarkLabel(nullLabel); ilg.MarkLabel(falseLabel); if (emitUnboxed) ((MaybePrimitiveExpr)_elseExpr).EmitUnboxed(rhc, objx, ilg); else _elseExpr.Emit(rhc, objx, ilg); ilg.MarkLabel(endLabel); }
private void DoEmitPrimOrStatic(ObjExpr fn, TypeBuilder tb, bool isStatic) { MethodAttributes attribs = isStatic ? MethodAttributes.Static | MethodAttributes.Public : MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; string methodName = isStatic ? "invokeStatic" : "invokePrim"; MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, GetReturnType(), _argTypes); if ( ! isStatic ) SetCustomAttributes(baseMB); CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this)); GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); EmitBody(Objx, baseIlg, _retType, _body); if ( _body.HasNormalExit() ) baseIlg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } // Generate the regular invoke, calling the static or prim method MethodBuilder regularMB = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), GetArgTypes()); SetCustomAttributes(regularMB); CljILGen regIlg = new CljILGen(regularMB.GetILGenerator()); if ( ! isStatic ) regIlg.Emit(OpCodes.Ldarg_0); for(int i = 0; i < _argTypes.Length; i++) { regIlg.EmitLoadArg(i+1); HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]); } regIlg.Emit(OpCodes.Call,baseMB); if ( GetReturnType().IsValueType) regIlg.Emit(OpCodes.Box,GetReturnType()); regIlg.Emit(OpCodes.Ret); }
private void DoEmit(ObjExpr fn, TypeBuilder tb) { MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; MethodBuilder mb = tb.DefineMethod(GetMethodName(), attribs, GetReturnType(), GetArgTypes()); SetCustomAttributes(mb); CljILGen baseIlg = new CljILGen(mb.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); _body.Emit(RHC.Return, fn, baseIlg); if ( _body.HasNormalExit() ) baseIlg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } if (IsExplicit) tb.DefineMethodOverride(mb, _explicitMethodInfo); }
internal void LightEmit(ObjExpr fn, Type fnType) { if (DynMethod != null) return; if (Prim != null || fn.IsStatic) throw new InvalidOperationException("No light compile allowed for static methods or methods with primitive interfaces"); Type[] argTypes = ClrExtensions.ArrayInsert(fnType,GetArgTypes()); DynamicMethod meth = new DynamicMethod(GetMethodName(), GetReturnType(), argTypes, true); CljILGen baseIlg = new CljILGen(meth.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); //GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); _body.Emit(RHC.Return, fn, baseIlg); if (_body.HasNormalExit()) baseIlg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } DynMethod = meth; }
void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { List<LocalBuilder> locals = new List<LocalBuilder>(); for (int i = 0; i < _bindingInits.count(); i++) { BindingInit bi = (BindingInit)_bindingInits.nth(i); Type primType = Compiler.MaybePrimitiveType(bi.Init); if (primType != null) { LocalBuilder local = ilg.DeclareLocal(primType); locals.Add(local); GenContext.SetLocalName(local, bi.Binding.Name); bi.Binding.LocalVar = local; ((MaybePrimitiveExpr)bi.Init).EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stloc, local); } else { LocalBuilder local = ilg.DeclareLocal(typeof(Object)); locals.Add(local); GenContext.SetLocalName(local, bi.Binding.Name); bi.Binding.LocalVar = local; bi.Init.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stloc, local); } } Label loopLabel = ilg.DefineLabel(); ilg.MarkLabel(loopLabel); try { if (_isLoop) Var.pushThreadBindings(PersistentHashMap.create(Compiler.LoopLabelVar, loopLabel)); if (emitUnboxed) ((MaybePrimitiveExpr)_body).EmitUnboxed(rhc, objx, ilg); else _body.Emit(rhc, objx, ilg); } finally { if (_isLoop) Var.popThreadBindings(); } }
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 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); }
public override void Emit(ObjExpr fn, TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, ReturnType, ArgTypes); SetCustomAttributes(mb); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label loopLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, SpanMap); try { Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this)); ilg.MarkLabel(loopLabel); EmitBody(Objx,ilg,_retType,Body); if ( Body.HasNormalExit() ) ilg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } if (IsExplicit) tb.DefineMethodOverride(mb, ExplicitMethodInfo); }
void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { Label nullLabel = ilg.DefineLabel(); Label falseLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); Label trueLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, _sourceSpan); StaticMethodExpr sme = _testExpr as StaticMethodExpr; if (sme != null && sme.CanEmitIntrinsicPredicate()) { sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel); } else if (Compiler.MaybePrimitiveType(_testExpr) == typeof(bool)) { ((MaybePrimitiveExpr)_testExpr).EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Brfalse, falseLabel); } else { LocalBuilder tempLoc = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(tempLoc, "test"); _testExpr.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Stloc, tempLoc); ilg.Emit(OpCodes.Brfalse, nullLabel); ilg.Emit(OpCodes.Ldloc, tempLoc); ilg.Emit(OpCodes.Isinst, typeof(bool)); ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Cgt_Un); ilg.Emit(OpCodes.Brfalse, trueLabel); ilg.Emit(OpCodes.Ldloc, tempLoc); ilg.Emit(OpCodes.Unbox_Any, typeof(bool)); ilg.Emit(OpCodes.Ldc_I4_0); ilg.Emit(OpCodes.Ceq); ilg.Emit(OpCodes.Brtrue, falseLabel); } ilg.MarkLabel(trueLabel); if (emitUnboxed) { ((MaybePrimitiveExpr)_thenExpr).EmitUnboxed(rhc, objx, ilg); } else { _thenExpr.Emit(rhc, objx, ilg); } if (_thenExpr.HasNormalExit()) { ilg.Emit(OpCodes.Br, endLabel); } ilg.MarkLabel(nullLabel); ilg.MarkLabel(falseLabel); if (emitUnboxed) { ((MaybePrimitiveExpr)_elseExpr).EmitUnboxed(rhc, objx, ilg); } else { _elseExpr.Emit(rhc, objx, ilg); } ilg.MarkLabel(endLabel); }
private void DoEmitStatic(ObjExpr fn, TypeBuilder tb) { MethodAttributes attribs = MethodAttributes.Static | MethodAttributes.Public; string methodName = "invokeStatic"; Type returnType = ReturnType; MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, returnType, _argTypes); CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); EmitBody(Objx, baseIlg, _retType, Body); if (Body.HasNormalExit()) baseIlg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } // Generate the regular invoke, calling the static method { MethodBuilder regularMB = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), ArgTypes); SetCustomAttributes(regularMB); CljILGen regIlg = new CljILGen(regularMB.GetILGenerator()); for (int i = 0; i < _argTypes.Length; i++) { regIlg.EmitLoadArg(i + 1); HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]); } GenContext.EmitDebugInfo(baseIlg, SpanMap); regIlg.Emit(OpCodes.Call, baseMB); if (ReturnType.IsValueType) regIlg.Emit(OpCodes.Box, ReturnType); regIlg.Emit(OpCodes.Ret); } // Generate primInvoke if prim if (Prim != null) { MethodAttributes primAttribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; string primMethodName = "invokePrim"; Type primReturnType; if (_retType == typeof(double) || _retType == typeof(long)) primReturnType = ReturnType; else primReturnType = typeof(object); MethodBuilder primMB = tb.DefineMethod(primMethodName, primAttribs, primReturnType, _argTypes); SetCustomAttributes(primMB); CljILGen primIlg = new CljILGen(primMB.GetILGenerator()); for (int i = 0; i < _argTypes.Length; i++) { primIlg.EmitLoadArg(i + 1); //HostExpr.EmitUnboxArg(fn, primIlg, _argTypes[i]); } primIlg.Emit(OpCodes.Call, baseMB); if (Body.HasNormalExit()) primIlg.Emit(OpCodes.Ret); } }
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(); } 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); } }
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 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 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); }
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); }
public virtual void Emit(ObjExpr fn, TypeBuilder tb) { MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.Public, ReturnType, ArgTypes); CljILGen ilg = new CljILGen(mb.GetILGenerator()); Label loopLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, SpanMap); try { Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this)); ilg.MarkLabel(loopLabel); Body.Emit(RHC.Return,fn,ilg); ilg.Emit(OpCodes.Ret); } finally { Var.popThreadBindings(); } }