public static void CompareEq(JavaType stackTop, JavaType stackTop2, Mono.Cecil.Cil.Instruction cilInst, JavaCode code) { if (stackTop.Equals(SpanType) && (stackTop2.PrimitiveType == TypeCode.Int64 || stackTop2.PrimitiveType == TypeCode.UInt64)) { // compare Span with long throw new InvalidProgramException(); } if (stackTop2.Equals(SpanType) && (stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64)) { if (cilInst.Previous == null || cilInst.Previous.OpCode.Code != Code.Conv_U || cilInst.Previous.Previous == null || cilInst.Previous.Previous.OpCode.Code != Code.Ldc_I4_0) { // make sure the program is comparing the span address against // a zero value, which we can convert to a null reference. // ldarg.1 (span argument) // ldc.i4.0 // conv.u // bne.un label throw new InvalidProgramException(); } // compare long with Span code.NewInstruction(0x58 /* pop2 */, null, null); code.NewInstruction(0x01 /* aconst_null */, null, null); } }
public static bool LoadStore(bool isLoad, CilType stackTop, JavaType opcodeType, CilType dataType, JavaCode code) { if (stackTop.Equals(SpanType) && code.Method.Class.Name != SpanType.ClassName) { string opcodeDescr; if (opcodeType == null) { opcodeType = CilType.SystemValueType; opcodeDescr = ""; // at this point we should have been called from LoadObject or // StoreObject in CodeMisc to handle a ldobj/stobj instruction, // so make sure the pointer-span element is a value type if (dataType.IsGenericParameter || (!dataType.IsValueClass)) { throw new InvalidProgramException(); } code.NewInstruction(0x12 /* ldc */, dataType.AsWritableClass, null); // make sure the stack has room for three parameters: // 'this', value reference (in case of Store), and class code.StackMap.PushStack(JavaType.ObjectType); code.StackMap.PushStack(JavaType.ObjectType); code.StackMap.PushStack(JavaType.ObjectType); code.StackMap.PopStack(CilMain.Where); code.StackMap.PopStack(CilMain.Where); code.StackMap.PopStack(CilMain.Where); } else { if (opcodeType.Equals(JavaType.ShortType) && stackTop.GenericParameters != null && stackTop.GenericParameters[0].Equals(JavaType.CharacterType)) { opcodeType = JavaType.CharacterType; } opcodeDescr = opcodeType.ToDescriptor(); } var voidType = JavaType.VoidType; var spanMethod = isLoad ? (new JavaMethodRef("Load" + opcodeDescr, opcodeType)) : (new JavaMethodRef("Store" + opcodeDescr, voidType, opcodeType)); if (opcodeDescr == "") { spanMethod.Parameters.Add(new JavaFieldRef("", JavaType.ClassType)); } code.NewInstruction(0xB6 /* invokevirtual */, SpanType, spanMethod); if (isLoad) { code.StackMap.PushStack(CilType.From(opcodeType)); } return(true); } return(false); }
public static bool Box(CilType intoType, JavaType spanType, JavaCode code) { if (spanType.Equals(SpanType) && intoType.IsByReference) { code.NewInstruction(0xB6 /* invokevirtual */, SpanType, new JavaMethodRef("Box", CilType.SystemValueType)); code.StackMap.PushStack(CilType.SystemValueType); return(true); } return(false); }
public static bool Clear(JavaType stackTop, CilType dataType, JavaCode code) { if (stackTop.Equals(SpanType) && dataType.IsValueClass && code.Method.Class.Name != SpanType.ClassName) { // if initobj is called on a span or pointer, call Span<T>.Clear() code.NewInstruction(0xB6 /* invokevirtual */, SpanType, new JavaMethodRef("Clear", JavaType.VoidType)); return(true); } return(false); }
public static bool CompareGtLt(JavaType stackTop, JavaType stackTop2, JavaCode code) { if (stackTop.Equals(SpanType) && stackTop2.Equals(SpanType)) { code.NewInstruction(0x01 /* aconst_null */, null, null); code.StackMap.PushStack(CilType.SystemTypeType); code.NewInstruction(0xB8 /* invokestatic */, SpanType, new JavaMethodRef("CompareTo" + CilMain.EXCLAMATION, JavaType.IntegerType, SpanType, SpanType, CilType.SystemTypeType)); code.StackMap.PopStack(CilMain.Where); // null type return(true); } return(false); }
public static bool AddOffset(JavaType offsetType, JavaType spanType, JavaCode code) { if (spanType.Equals(SpanType)) { code.StackMap.PushStack(spanType); if (offsetType.Equals(JavaType.IntegerType)) { code.NewInstruction(0x85 /* i2l */, null, null); offsetType = JavaType.LongType; } code.StackMap.PushStack(offsetType); bool loadedType = false; if (spanType is CilType spanType2) { if ((!spanType2.HasGenericParameters) && spanType2.GenericParameters != null && spanType2.GenericParameters[0] is CilType spanPointerType && (!spanPointerType.IsGenericParameter)) { GenericUtil.LoadMaybeGeneric(spanPointerType, code); loadedType = true; } } if (!loadedType) { code.NewInstruction(0x01 /* aconst_null */, null, null); code.StackMap.PushStack(CilType.SystemTypeType); } code.NewInstruction(0xB6 /* invokevirtual */, SpanType, new JavaMethodRef("Add", SpanType, offsetType, CilType.SystemTypeType)); code.StackMap.PopStack(CilMain.Where); // span type code.StackMap.PopStack(CilMain.Where); // offset return(true); } return(false); }
public override bool AssignableTo(JavaType other) { if (base.AssignableTo(other)) { return(true); } if (SuperTypes != null) { foreach (var sup in SuperTypes) { if ((!sup.Equals(JavaType.ObjectType)) && (other.Equals(sup) || sup.AssignableTo(other))) { return(true); } } } return(false); }
static byte TestGtLt(JavaCode code, JavaType stackTop, JavaType stackTop2, bool greater, bool unsigned_unordered) { byte op; // // for floating point, normal comparison returns 0 if either value // is NaN, while unordered comparison returns 1. we have fcmp/dcmp // variants which return either 1 or -1. following the comparison, // we have ifgt/iflt to check if the result is either greater than // or less than 0. we consider all this when picking the opcode: // // test normal compare unordered compare // greater than ifgt xcmpl xcmpg // less than iflt xcmpg xcmpl // if (stackTop.PrimitiveType == TypeCode.Single) { op = (byte)((greater != unsigned_unordered) ? 0x95 // fcmpl : 0x96); // fcmpg } else if (stackTop.PrimitiveType == TypeCode.Double) { op = (byte)((greater != unsigned_unordered) ? 0x97 // dcmpl : 0x98); // dcmpg } // // for unsigned integer comparison, we use library function // system.UInt{32,64}.CompareTo, followed by ifgt/iflt // else if (unsigned_unordered && stackTop.PrimitiveType != TypeCode.Char) { char typeChar; int typeBits; string typeName = null; if (stackTop.PrimitiveType == TypeCode.SByte || stackTop.PrimitiveType == TypeCode.Byte) { typeChar = 'B'; typeBits = 0; typeName = "Byte"; } else if (stackTop.PrimitiveType == TypeCode.Int16 || stackTop.PrimitiveType == TypeCode.UInt16) { typeChar = 'S'; typeBits = 16; } else if (stackTop.PrimitiveType == TypeCode.Int32 || stackTop.PrimitiveType == TypeCode.UInt32) { typeChar = 'I'; typeBits = 32; } else if (stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64) { typeChar = 'J'; typeBits = 64; } else if (greater && stackTop.Equals(JavaStackMap.Null)) { // per MS CLI Partition III table 4 note 2, 'cgt.un' // can be used to check for a non-null reference return(0xA6); // if_acmpne } else { if (CodeSpan.CompareGtLt(stackTop, stackTop2, code)) { return((byte)(greater ? 0x9D // ifgt : 0x9B)); // iflt } throw new InvalidProgramException(); } if (typeBits != 0) { typeName = "UInt" + typeBits.ToString(); } code.NewInstruction(0xB8 /* invokestatic */, new JavaType(0, 0, $"system.{typeName}"), new JavaMethodRef("CompareTo", $"({typeChar}{typeChar})I", CilMain.Where)); /* * new JavaType(0, 0, $"java.lang.{typeName}"), * new JavaMethodRef("compareUnsigned", * $"({typeChar}{typeChar})I", CilMain.Where));*/ op = 0; } // // for signed long comparison, we use lcmp followed by ifgt/iflt // else if (stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64) { op = 0x94; // lcmp (long) } // // for signed integer comparison, we have if_icmplt/if_icmpgt // which directly compare two integers and branch // else if (stackTop.PrimitiveType == TypeCode.Int32 || stackTop.PrimitiveType == TypeCode.UInt32 || stackTop.PrimitiveType == TypeCode.Int16 || stackTop.PrimitiveType == TypeCode.UInt16 || stackTop.PrimitiveType == TypeCode.SByte || stackTop.PrimitiveType == TypeCode.Byte || stackTop.PrimitiveType == TypeCode.Char || stackTop.PrimitiveType == TypeCode.Boolean) { return((byte)(greater ? 0xA3 // if_icmpgt : 0xA1)); // if_icmplt } else { throw new InvalidProgramException(); } // // return the selected opcode // if (op != 0) { code.NewInstruction(op, null, null); } return((byte)(greater ? 0x9D // ifgt : 0x9B)); // iflt }
static bool IsGenericOrEqual(JavaType pThis, CilType pBase) => pBase.IsGenericParameter || pThis.Equals(pBase);