Пример #1
0
    public static void CreateBinaryOperationIC(ILGen.BaseILGenerator ilGen, IR.NodeType nodeType, int resultIndex, mdr.ValueTypes i0Type, mdr.ValueTypes i1Type, bool i0TypeCheck, bool i1TypeCheck)
    {
      ilGen.WriteComment("IC method for {0}({1}, {2}) written to {3}", nodeType, i0Type, i0Type, resultIndex);

      var values = ilGen.DeclareLocal(CodeGen.Types.DValue.ArrayOf);
      ilGen.Ldarg_CallFrame();
      ilGen.Ldfld(CodeGen.Types.CallFrame.Values);
      ilGen.Stloc(values);

      ///Try to make a better guess on the unknown types. 
      if (i0Type == mdr.ValueTypes.DValueRef)
      {
        if (i1Type != mdr.ValueTypes.DValueRef)
          i0Type = i1Type;
        else
          i0Type = i1Type = mdr.ValueTypes.Int32; //Just a guess! 
      }
      else if (i1Type == mdr.ValueTypes.DValueRef)
        i1Type = i0Type;

      var t0 = ilGen.DeclareLocal(CodeGen.Types.ClrSys.Int32);
      //if (i0TypeCheck)
      {
        LoadValue(ilGen, values, resultIndex, mdr.ValueTypes.DValueRef);
        ilGen.Call(CodeGen.Types.DValue.GetValueType);
        ilGen.Stloc(t0);
      }

      var t1 = ilGen.DeclareLocal(CodeGen.Types.ClrSys.Int32);
      //if (i0TypeCheck)
      {
        LoadValue(ilGen, values, resultIndex + 1, mdr.ValueTypes.DValueRef);
        ilGen.Call(CodeGen.Types.DValue.GetValueType);
        ilGen.Stloc(t1);
      }

      var guardFail = ilGen.DefineLabel();
      var done = ilGen.DefineLabel();

      ilGen.Ldloc(t0);
      ilGen.Ldc_I4(8);
      ilGen.Shl();
      ilGen.Ldloc(t1);
      ilGen.Or();
      ilGen.Ldc_I4(((int)i0Type << 8) | (int)i1Type);
      ilGen.Bne_Un(guardFail);

      var operation = CodeGen.Types.Operations.Binary.Get(nodeType);
      var mi = operation.Get(i0Type, i1Type);
      var returnType = operation.ReturnType(i0Type, i1Type);
      if (returnType == mdr.ValueTypes.DValueRef)
      {
        Debug.Assert(mi.GetParameters().Length == 3 && mi.GetParameters()[2].ParameterType == CodeGen.Types.TypeOf(mdr.ValueTypes.DValueRef), "Invalid situation, method {0} must get a third parameter of type 'ref DValue'", mi);
        LoadValue(ilGen, values, resultIndex, i0Type);
        LoadValue(ilGen, values, resultIndex + 1, i1Type);
        LoadValue(ilGen, values, resultIndex, mdr.ValueTypes.DValueRef);
        ilGen.Call(mi);
      }
      else
      {
        LoadValue(ilGen, values, resultIndex, mdr.ValueTypes.DValueRef);
        LoadValue(ilGen, values, resultIndex, i0Type);
        LoadValue(ilGen, values, resultIndex + 1, i1Type);
        ilGen.Call(mi);
        ilGen.Call(CodeGen.Types.DValue.Set.Get(returnType));
      }
      ilGen.Br(done);

      ilGen.MarkLabel(guardFail);
      ilGen.Ldarg_CallFrame();
      ilGen.Ldarg_1();
      ilGen.Ldc_I4((int)nodeType);
      ilGen.Ldc_I4(resultIndex);
      ilGen.Ldloc(t0);
      ilGen.Ldloc(t1);
      ilGen.Ldc_I4(i0TypeCheck);
      ilGen.Ldc_I4(i1TypeCheck);
      ilGen.Call(CodeGen.Types.Operations.ICMethods.RunAndUpdateBinaryOperationIC);
      ilGen.Ret();

      ilGen.MarkLabel(done);
    }
Пример #2
0
    public static void CreateUnaryOperationIC(ILGen.BaseILGenerator ilGen, IR.NodeType nodeType, int resultIndex, mdr.ValueTypes i0Type, bool i0TypeCheck)
    {
      ilGen.WriteComment("IC method for {0}({1}, {2}) written to {3}", nodeType, i0Type, i0Type, resultIndex);

      var values = ilGen.DeclareLocal(CodeGen.Types.DValue.ArrayOf);
      ilGen.Ldarg_CallFrame();
      ilGen.Ldfld(CodeGen.Types.CallFrame.Values);
      ilGen.Stloc(values);

      var t0 = ilGen.DeclareLocal(CodeGen.Types.ClrSys.Int32);
      //if (i0TypeCheck)
      {
        LoadValue(ilGen, values, resultIndex, mdr.ValueTypes.DValueRef);
        ilGen.Call(CodeGen.Types.DValue.GetValueType);
        ilGen.Stloc(t0);
      }

      var guardFail = ilGen.DefineLabel();
      var done = ilGen.DefineLabel();

      var operation = CodeGen.Types.Operations.Unary.Get(nodeType);

      if (i0Type == mdr.ValueTypes.DValueRef) //Just a better guess!
        i0Type = operation.ReturnType(i0Type); //we will need to repeat the lookup again

      ilGen.Ldloc(t0);
      ilGen.Ldc_I4((int)i0Type);
      ilGen.Bne_Un(guardFail);

      var mi = operation.Get(i0Type);
      var returnType = operation.ReturnType(i0Type);

      if (returnType == mdr.ValueTypes.DValueRef)
      {
        Debug.Assert(mi.GetParameters().Length == 2 && mi.GetParameters()[1].ParameterType == CodeGen.Types.TypeOf(mdr.ValueTypes.DValueRef), "Invalid situation, method {0} must get a second parameter of type 'ref DValue'", mi);
        LoadValue(ilGen, values, resultIndex, i0Type);
        LoadValue(ilGen, values, resultIndex, mdr.ValueTypes.DValueRef);
        ilGen.Call(mi);
      }
      else
      {
        LoadValue(ilGen, values, resultIndex, mdr.ValueTypes.DValueRef);
        LoadValue(ilGen, values, resultIndex, i0Type);
        ilGen.Call(mi);
        ilGen.Call(CodeGen.Types.DValue.Set.Get(returnType));
      }
      ilGen.Br(done);

      ilGen.MarkLabel(guardFail);
      ilGen.Ldarg_CallFrame();
      ilGen.Ldarg_1();
      ilGen.Ldc_I4((int)nodeType);
      ilGen.Ldc_I4(resultIndex);
      ilGen.Ldloc(t0);
      ilGen.Ldc_I4(i0TypeCheck);
      ilGen.Call(CodeGen.Types.Operations.ICMethods.RunAndUpdateUnaryOperationIC);
      ilGen.Ret();

      ilGen.MarkLabel(done);
    }