/// <summary> /// brtrue 命令を出力します。スタックのトップが真である時に分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBrtrue(Emit::Label label) { gen.Emit(Emit::OpCodes.Brtrue, label); // ↓は label との距離が分からないので使えるかどうか分からない。 // gen.Emit(Emit::OpCodes.Brtrue_S,label); }
public bool Emit(afh.Reflection.ILGeneratorHelper gh, System.Reflection.Emit.Label label) { Emit::Label l = gh.CreateLabel(); gh.EmitLdarg(1); gh.EmitLdc(this.c1); gh.EmitBltUnS(l); gh.EmitLdarg(1); gh.EmitLdc(this.c2); gh.EmitBleUn(label); gh.MarkLabel(l); return(true); }
public BenchMethod(Ref::MethodInfo minfo, BenchMethodAttribute attr) { this.minfo = minfo; this.attr = attr; Emit::DynamicMethod m = new Emit::DynamicMethod( "bench", typeof(TimeSpan), new System.Type[] { typeof(int) }, minfo.DeclaringType ); // // 宣言 // Emit::ILGenerator ilgen = m.GetILGenerator(); System.Type type_dt = typeof(System.DateTime); Emit::LocalBuilder loc_start = ilgen.DeclareLocal(type_dt); Emit::LocalBuilder loc_end = ilgen.DeclareLocal(type_dt); Emit::LocalBuilder loc_i = ilgen.DeclareLocal(typeof(int)); Ref::MethodInfo m_get_Now = type_dt.GetMethod("get_Now"); Ref::MethodInfo m_op_Subtraction = type_dt.GetMethod("op_Subtraction", new System.Type[] { type_dt, type_dt }); Emit::Label label_loopC = ilgen.DefineLabel(); Emit::Label label_loopJ = ilgen.DefineLabel(); // // ロジック // //-- pro ilgen.Emit(Emit::OpCodes.Call, m_get_Now); ilgen.Emit(Emit::OpCodes.Stloc, loc_start); //-- loop ilgen.Emit(Emit::OpCodes.Ldc_I4_0); ilgen.Emit(Emit::OpCodes.Dup); // ilgen.Emit(Emit::OpCodes.Stloc, loc_i); ilgen.Emit(Emit::OpCodes.Br_S, label_loopJ); ilgen.MarkLabel(label_loopC); ilgen.Emit(Emit::OpCodes.Call, minfo); if (minfo.ReturnType != typeof(void)) { ilgen.Emit(Emit::OpCodes.Pop); } ilgen.Emit(Emit::OpCodes.Ldloc, loc_i); ilgen.Emit(Emit::OpCodes.Ldc_I4_1); ilgen.Emit(Emit::OpCodes.Add); ilgen.Emit(Emit::OpCodes.Dup); // ilgen.Emit(Emit::OpCodes.Stloc, loc_i); ilgen.MarkLabel(label_loopJ); //ilgen.Emit(Emit::OpCodes.Ldloc,loc_i); ilgen.Emit(Emit::OpCodes.Ldarg_0); ilgen.Emit(Emit::OpCodes.Blt_S, label_loopC); //-- epi ilgen.Emit(Emit::OpCodes.Call, m_get_Now); ilgen.Emit(Emit::OpCodes.Stloc, loc_end); ilgen.Emit(Emit::OpCodes.Ldloc, loc_end); ilgen.Emit(Emit::OpCodes.Ldloc, loc_start); ilgen.Emit(Emit::OpCodes.Call, m_op_Subtraction); ilgen.Emit(Emit::OpCodes.Ret); this.meth = (MeasureTime)m.CreateDelegate(typeof(MeasureTime)); }
private System.Predicate <char> CreateHandler( bool positive, IClassHandler[] handlers, bool[] issub, out IClassHandler[] child ) { int[] borders; { Gen::List <int> borders_l = new System.Collections.Generic.List <int>(); bool current = true; for (int i = 0; i < issub.Length; i++) { if (issub[i] == current) { continue; } borders_l.Add(i); // * current = issub[i]; } // issub: [F T T T F F T T F T F F F T T T ] // brdrs: * * * * * * * @ borders_l.Add(issub.Length); // @ borders = borders_l.ToArray(); } afh.Reflection.DynamicMethodCreater <CompiledClassHandler, System.Predicate <char> > gh = new afh.Reflection.DynamicMethodCreater <CompiledClassHandler, System.Predicate <char> >("<generated>", false); Gen::List <IClassHandler> child_l = new Gen::List <IClassHandler>(); Emit::Label label = gh.CreateLabel(); for (int k = 0, kM = borders.Length - 1; k < kM; k++) { for (int i = borders[k]; i < borders[k + 1]; i++) { //-- それぞれのハンドラに応じた処理 // 判定陽性 → goto label; // 判定陰性 → その儘次へ流れる if (!handlers[i].Emit(gh, label)) { // child リストから呼び出す場合 int iChild = child_l.Count; child_l.Add(handlers[i]); // (s1)= this.child[iChild] gh.EmitLdarg(0); gh.EmitLdfld(typeof(CompiledClassHandler), "child", false, true); gh.EmitLdc(iChild); gh.EmitLdelem(typeof(IClassHandler)); // if((s1).Judge(c))goto label; gh.EmitLdarg(1); gh.EmitCall(handlers[i].GetType(), false, false, "Judge", typeof(char)); gh.EmitBrtrue(label); } } // もう終わる時 if (k + 1 == kM) { break; } else { Emit::Label newlabel = gh.CreateLabel(); gh.EmitBr(newlabel); gh.MarkLabel(label); label = newlabel; positive = !positive; } } gh.EmitLdc(!positive); gh.EmitRet(); gh.MarkLabel(label); gh.EmitLdc(positive); gh.EmitRet(); child = child_l.ToArray(); return(gh.Instantiate(this)); }
/// <summary> /// ラベルを出力します。 /// </summary> /// <param name="label">出力するラベルを指定します。</param> public void MarkLabel(Emit::Label label) { gen.MarkLabel(label); }
/// <summary> /// bge.s 命令を出力します。スタックの上の二つの値を符号付き整数として比較して、 /// 一つ目の値の方が二つ目の値以上の時に、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBgeS(Emit::Label label) { gen.Emit(Emit::OpCodes.Bge_S, label); }
/// <summary> /// blt.s 命令を出力します。スタックの上の二つの値を符号付き整数として比較して、 /// 一つ目の値の方が二つ目の値よりも小さい時に、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBltS(Emit::Label label) { gen.Emit(Emit::OpCodes.Blt_S, label); }
/// <summary> /// bgt.un.s 命令を出力します。スタックの上の二つの値を符号無し整数として比較して、 /// 一つ目の値の方が二つ目の値よりも大きい時に、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBgtUnS(Emit::Label label) { gen.Emit(Emit::OpCodes.Bgt_Un_S, label); }
/// <summary> /// ble.un.s 命令を出力します。スタックの上の二つの値を符号無し整数として比較して、 /// 一つ目の値の方が二つ目の値以下の時に、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBleUnS(Emit::Label label) { gen.Emit(Emit::OpCodes.Ble_Un_S, label); }
/// <summary> /// bne 命令を出力します。スタックの上の二つの値が異なる時に、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBneS(Emit::Label label) { gen.Emit(Emit::OpCodes.Bne_Un_S, label); }
/// <summary> /// beq 命令を出力します。スタックの上の二つの値が等しい時に、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBeqS(Emit::Label label) { gen.Emit(Emit::OpCodes.Beq_S, label); }
/// <summary> /// br 命令を出力します。無条件で、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBrS(Emit::Label label) { gen.Emit(Emit::OpCodes.Br_S, label); }
/// <summary> /// brfalse 命令を出力します。スタックのトップが偽である時に、近くに分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBrfalseS(Emit::Label label) { gen.Emit(Emit::OpCodes.Brfalse_S, label); }
/// <summary> /// ble 命令を出力します。スタックの上の二つの値を符号付き整数として比較して、 /// 一つ目の値の方が二つ目の値以下の時に分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBle(Emit::Label label) { gen.Emit(Emit::OpCodes.Ble, label); }
/// <summary> /// bge.un 命令を出力します。スタックの上の二つの値を符号無し整数として比較して、 /// 一つ目の値の方が二つ目の値以上の時に分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBgeUn(Emit::Label label) { gen.Emit(Emit::OpCodes.Bge_Un, label); }
/// <summary> /// blt.un 命令を出力します。スタックの上の二つの値を符号無し整数として比較して、 /// 一つ目の値の方が二つ目の値よりも小さい時に分岐を行います。 /// </summary> /// <param name="label">分岐先のラベルを指定します。</param> public void EmitBltUn(Emit::Label label) { gen.Emit(Emit::OpCodes.Blt_Un, label); }