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); }
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); }