public static CilType CastMaybeGeneric(CilType castType, bool valueOnly, JavaCode code) { if (!castType.IsGenericParameter) { return(castType); } if (!valueOnly) { GenericUtil.ValueLoad(code); } var genericMark = CilMain.GenericStack.Mark(); var(resolvedType, resolvedIndex) = CilMain.GenericStack.Resolve(castType.JavaName); if (resolvedIndex == 0) { if (valueOnly) { // this flag is set when called from LoadFieldAddress. we can cast // the generic field to the actual type only if it is a value type if (resolvedType.IsValueClass) { castType = resolvedType; code.NewInstruction(0xC0 /* checkcast */, castType.AsWritableClass, null); } else if (castType.IsByReference) { var boxedType = new BoxedType(resolvedType, false); code.NewInstruction(0xC0 /* checkcast */, boxedType, null); castType = boxedType; } } else { // this flag is clear whe called from LoadFieldValue and // PushMethodReturnType. we can cast to any known actual types. var arrayRank = castType.GetMethodGenericParameter()?.ArrayRank ?? 0; castType = (arrayRank == 0) ? resolvedType : resolvedType.AdjustRank(arrayRank); if (!castType.IsReference) { var boxedType = new BoxedType(castType, false); code.NewInstruction(0xC0 /* checkcast */, boxedType, null); boxedType.GetValue(code); } else { code.NewInstruction(0xC0 /* checkcast */, castType.AsWritableClass, null); } } } CilMain.GenericStack.Release(genericMark); return(castType); }
public static bool CheckCast(CilType castType, bool @throw, JavaCode code) { if (object.ReferenceEquals(castType, GenericArrayType) || (castType.IsArray && (castType.IsInterface || castType.IsGenericParameter || castType.ClassName == JavaType.ObjectType.ClassName || castType.ClassName == CilType.SystemValueType.ClassName))) { // if casting to Object[], ValueType[], to an array of interface type, // or to an array of a generic parameter, we can't rely on a simple // 'checkcast' or 'instanceof', because the jvm will permit the cast // of a value type array to the aforementioned reference types. // // instead, we generate a call to system.Array.CheckCast in baselib, // except if we are generating code for the system.Array class itself. if (code.Method.Class.Name.StartsWith("system.Array")) { return(false); } // note the caller of this method already popped the stack once. // which we have to undo that, before we push anything else. code.StackMap.PushStack(JavaType.ObjectType); // array var method = new JavaMethodRef("CheckCast", JavaType.ObjectType); method.Parameters.Add(new JavaFieldRef("", JavaType.ObjectType)); if (object.ReferenceEquals(castType, GenericArrayType) || castType.IsGenericParameter) { method.Parameters.Add(new JavaFieldRef("", CilType.SystemTypeType)); GenericUtil.LoadMaybeGeneric(castType, code); // CilType.SystemTypeType pushed to the stack } else { method.Parameters.Add(new JavaFieldRef("", JavaType.ClassType)); code.NewInstruction(0x12 /* ldc */, castType.AdjustRank(-1), null); code.StackMap.PushStack(JavaType.ClassType); } method.Parameters.Add(new JavaFieldRef("", JavaType.BooleanType)); code.NewInstruction(0x12 /* ldc */, null, (int)(@throw ? 1 : 0)); code.StackMap.PushStack(JavaType.IntegerType); // boolean code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType, method); code.StackMap.PopStack(CilMain.Where); // boolean code.StackMap.PopStack(CilMain.Where); // class/type code.StackMap.PopStack(CilMain.Where); // array return(true); } return(false); }
static void LoadGenericInstance_3_N(CilType loadType, int genericCount, List <JavaFieldRef> parameters, JavaCode code) { if (genericCount <= 8) { // handling for the less common case of a generic instace with // less than eight arguments. we don't check if the provided // type arguments are concrete or generic, and call a GetType() // override for the appropriate number of parameters. // note that the first class argument to GetType was alredy // inserted by our caller, LoadMaybeGeneric(). for (int i = 0; i < genericCount; i++) { LoadMaybeGeneric(loadType.GenericParameters[i], code); // next parameter always has type system.Type parameters.Add(new JavaFieldRef("", CilType.SystemTypeType)); } } else { // generic handling for the less common case of a generic instace // with more than eight arguments. we don't check if the provided // type arguments are concrete or generic. we build an array of // system.Type references, and call GetType(class, system.Type[]). // note that the first class argument to GetType was alredy // inserted by our caller, LoadMaybeGeneric(). var arrayOfType = CilType.SystemTypeType.AdjustRank(1); parameters.Add(new JavaFieldRef("", arrayOfType)); code.NewInstruction(0x12 /* ldc */, null, genericCount); code.StackMap.PushStack(JavaType.IntegerType); code.NewInstruction(0xBD /* anewarray */, CilType.SystemTypeType, null); code.StackMap.PopStack(CilMain.Where); code.StackMap.PushStack(arrayOfType); for (int i = 0; i < genericCount; i++) { code.NewInstruction(0x59 /* dup */, null, null); code.StackMap.PushStack(arrayOfType); code.NewInstruction(0x12 /* ldc */, null, i); code.StackMap.PushStack(JavaType.IntegerType); LoadMaybeGeneric(loadType.GenericParameters[i], code); code.NewInstruction(0x53 /* aastore */, null, null); code.StackMap.PopStack(CilMain.Where); code.StackMap.PopStack(CilMain.Where); code.StackMap.PopStack(CilMain.Where); } } }
public static void Instance(JavaCode code, CodeLocals locals, Mono.Cecil.Cil.Instruction cilInst) { if (cilInst.Operand is TypeReference cilType && cilInst.Next != null) { var stackTop = (CilType)code.StackMap.PopStack(CilMain.Where); if (!stackTop.IsReference) { throw new InvalidProgramException(); // top of stack is a primitive type } var castType = (CilType)CilType.From(cilType); JavaType castClass = CilType.From(cilType).AsWritableClass; if (GenericUtil.ShouldCallGenericCast(stackTop, castType) || castType.IsGenericParameter) { code.StackMap.PushStack(stackTop); // casting to a generic type is done via GenericType.TestCast GenericUtil.CastToGenericType(cilType, 0, code); code.StackMap.PopStack(CilMain.Where); // stackTop if (!castType.IsGenericParameter) { code.NewInstruction(0xC0 /* checkcast */, castClass, null); } code.StackMap.PushStack(castClass); } else if (CodeArrays.CheckCast(castType, false, code)) { // if casting to Object[], ValueType[], to an array of // interface type, or to an array of a generic parameter, // then CodeArrays.CheckCast already generated a call to // system.Array.CheckCast in baselib, and we are done here if (!castType.IsGenericParameter) { // avoid cast since T[] might be a primitive array code.NewInstruction(0xC0 /* checkcast */, castClass, null); } code.StackMap.PushStack(castClass); } // // the cil 'isinst' casts the operand to the requested class, // but the jvm 'instanceof' only returns zero or one. so we // also use 'checkcast' to get the jvm to acknowledge the cast // // however, if the cil 'isinst' is immediately followed by // 'brtrue' or 'brfalse' then we don't have to actually cast // else if (!TestForBranch(code, castClass, cilInst.Next)) { ushort nextLabel = (ushort)cilInst.Next.Offset; TestAndCast(code, castClass, stackTop, nextLabel, locals); } }
public static CilType WrapMethodGenericParameter(CilType fromType, string newJavaName = null) { var newType = new CilType(); newType.CopyFrom(JavaType.ObjectType); newType.Flags = fromType.Flags | IS_GEN_PRM; newType.JavaName = newJavaName ?? fromType.JavaName; newType.GenericParameters = new List <CilType>(); newType.GenericParameters.Add(fromType); return(newType); }
CilType Clone() { var newType = new CilType(); newType.CopyFrom(this); newType.JavaName = JavaName; newType.SuperTypes = SuperTypes; newType.GenericParameters = GenericParameters; newType.Flags = Flags; return(newType); }
bool LoadFieldValue(string fldName, CilType fldType, CilType fldClass, bool isStatic, bool isVolatile) { if (isStatic && fldClass.HasGenericParameters) { fldClass = LoadStaticData(fldClass); isStatic = false; } byte op; if (!isStatic) { if (method.IsConstructor && LoadFieldInConstructor(fldName, fldType, fldClass)) { return(true); } PopObjectAndLoadFromSpan(fldClass); op = 0xB4; // getfield } else { op = 0xB2; // getstatic } code.NewInstruction(op, fldClass.AsWritableClass, new JavaFieldRef(fldName, fldType)); if (fldType is BoxedType boxedType) { boxedType.GetValue(code, isVolatile); fldType = boxedType.UnboxedType; if (fldType.IsReference) { if (fldType.IsGenericParameter && fldType.IsArray) { fldType = CodeArrays.GenericArrayType; } else if (!fldType.Equals(JavaType.ObjectType)) { code.NewInstruction(0xC0 /* checkcast */, fldType.AsWritableClass, null); } } } else if (fldType.IsGenericParameter) { var newType = GenericUtil.CastMaybeGeneric(fldType, false, code); fldType = (newType != fldType) ? newType : CilType.From(JavaType.ObjectType); } stackMap.PushStack(fldType); return(true); }
public static void LoadMaybeGeneric(CilType loadType, JavaCode code) { if (loadType.IsGenericParameter) { LoadGeneric(loadType.JavaName, code); } else { // all GetType variants take a first parameter of type java.lang.Class List <JavaFieldRef> parameters = new List <JavaFieldRef>(); parameters.Add(new JavaFieldRef("", JavaType.ClassType)); int arrayRank = loadType.ArrayRank; if (arrayRank == 0 || (!loadType.IsGenericParameter)) { code.NewInstruction(0x12 /* ldc */, loadType.AsWritableClass, null); } else { // for a generic type T[], we want to load just the element T, // and then (see below) call MakeArrayType on the result var loadTypeElem = loadType.AdjustRank(-arrayRank); code.NewInstruction(0x12 /* ldc */, loadTypeElem.AsWritableClass, null); } code.StackMap.PushStack(JavaType.ClassType); if (loadType.HasGenericParameters) { LoadGenericInstance(loadType, parameters, code); } code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType, new JavaMethodRef("GetType", CilType.SystemTypeType, parameters)); for (int i = 0; i < parameters.Count; i++) { code.StackMap.PopStack(CilMain.Where); } code.StackMap.PushStack(CilType.SystemTypeType); if (arrayRank != 0 && loadType.IsGenericParameter) { code.NewInstruction(0x12 /* ldc */, null, (int)arrayRank); code.StackMap.PushStack(JavaType.IntegerType); code.NewInstruction(0xB6 /* invokevirtual */, CilType.SystemTypeType, new JavaMethodRef("MakeArrayType", CilType.SystemTypeType, JavaType.IntegerType)); code.StackMap.PopStack(CilMain.Where); } } }
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); }
// // generate code to initialize the generic type field // public static void InitializeTypeField(CilType declType, JavaCode code) { code.NewInstruction(0x19 /* aload */, null, (int)0); code.StackMap.PushStack(declType); LoadMaybeGeneric(declType, code); code.NewInstruction(0xC0 /* checkcast */, CilType.SystemRuntimeTypeType, null); code.NewInstruction(0xB5 /* putfield */, declType, ConcreteTypeField); code.StackMap.PopStack(CilMain.Where); code.StackMap.PopStack(CilMain.Where); }
public override JavaType ResolveConflict(JavaType other) { // the ternary operator ?: may produce code that causes a conflict: // object x = flag ? (object) new A() : (object) new B(); // if we detect such a conflict at a branch target, we assume this // is the cause, and set the stack elements to a common denominator // or to the lowest common denominator, java.lang.Object if (IsReference && other.IsReference && other is CilType other2 && (!this.IsValueClass) && (!other2.IsValueClass)) { return(FindCommonSuperType(this, other2) ?? CilType.From(JavaType.ObjectType)); } return(null);
public static void MakeValueClass(JavaClass valueClass, CilType fromType, int numCastableInterfaces) { valueClass.Super = CilType.SystemValueType.ClassName; CreateDefaultConstructor(valueClass, fromType, numCastableInterfaces, true); CreateValueMethods(valueClass, fromType, numCastableInterfaces); if ((valueClass.Flags & JavaAccessFlags.ACC_ABSTRACT) == 0) { valueClass.Flags |= JavaAccessFlags.ACC_FINAL; } }
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); }
// // create default parameterless constructor. (it will be called at the // top of any method which allocates a value type local.) and note that // if this is a generic value type, this new constructor will be further // modified in GenericUtil.MakeGenericClass.FixConstructorsInFrom // static void CreateDefaultConstructor(JavaClass valueClass, CilType fromType, int numCastableInterfaces, bool initFields) { foreach (var oldMethod in valueClass.Methods) { if (oldMethod.Name == "<init>") { return; } } var code = CilMethod.CreateConstructor(valueClass, fromType.GenericParametersCount, true); if (fromType.HasGenericParameters) { code.StackMap = new JavaStackMap(); var genericMark = CilMain.GenericStack.Mark(); CilMain.GenericStack.EnterMethod(fromType, code.Method, true); // initialize the generic type field GenericUtil.InitializeTypeField(fromType, code); CilMain.GenericStack.Release(genericMark); code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where); } // init the array of generic interfaces InterfaceBuilder.InitInterfaceArrayField( fromType, numCastableInterfaces, code, 0); if (initFields) { var oldLabel = code.SetLabel(0xFFFF); InitializeInstanceFields(valueClass, fromType, null, code); code.SetLabel(oldLabel); } code.NewInstruction(0x19 /* aload */, null, (int)0); code.NewInstruction(0xB7 /* invokespecial */, new JavaType(0, 0, valueClass.Super), new JavaMethodRef("<init>", JavaType.VoidType)); code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where); if (code.MaxStack < 1) { code.MaxStack = 1; } code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null); }
public void Address(CilType arrayType) { stackMap.PopStack(CilMain.Where); // index if (arrayType == null) { arrayType = (CilType)stackMap.PopStack(CilMain.Where); } else { stackMap.PopStack(CilMain.Where); // array } var elemType = arrayType.AdjustRank(-arrayType.ArrayRank); if (elemType.IsReference) { if (elemType.IsGenericParameter) { // call system.Array.Box(object array, int index) code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType, new JavaMethodRef("Box", CilType.SystemValueType, JavaType.ObjectType, JavaType.IntegerType)); } else if (elemType.IsValueClass) { code.NewInstruction(0x32 /* aaload */, null, null); } else { // call system.Reference.Box(object a, int i) elemType = new BoxedType(elemType, false); code.NewInstruction(0xB8 /* invokestatic */, elemType, new JavaMethodRef("Box", elemType, JavaType.ObjectType, JavaType.IntegerType)); } stackMap.PushStack(elemType); } else { // call system.(PrimitiveType).Box(primitiveType[] a, int i) var typeCode = elemType.PrimitiveType; stackMap.PushStack(new BoxedType(elemType, false)); arrayType = elemType.AdjustRank(1); elemType = elemType.AsWritableClass; code.NewInstruction(0xB8 /* invokestatic */, elemType, new JavaMethodRef("Box", elemType, arrayType, JavaType.IntegerType)); } }
// // create a java generic class signature, this is used by // system.RuntimeType in baselib to provide more accurate reflection // public static string MakeGenericSignature(TypeDefinition fromType, string superName) { string signature = ""; if (fromType.GenericParameters.Count > 0) { signature = "<"; foreach (var prm in fromType.GenericParameters) { signature += prm.Name + ":Ljava/lang/Object;"; } signature += ">"; } signature += ClassSignature(superName, fromType.BaseType); if (fromType.HasInterfaces) { foreach (var ifc in fromType.Interfaces) { var name = CilType.From(ifc.InterfaceType).JavaName; if (name != "system.ValueMethod") { signature += ClassSignature(name, ifc.InterfaceType); } } } return(signature); string ClassSignature(string className, TypeReference fromType) { var signature = "L" + className.Replace('.', '/'); if (fromType is GenericInstanceType fromGenericType) { signature += "<"; foreach (var arg in fromGenericType.GenericArguments) { if (arg is GenericParameter genericArg) { signature += "T" + arg.Name + ";"; } else { signature += ClassSignature(CilType.From(arg).JavaName, arg); } } signature += ">"; } return(signature + ";"); } }
public static bool MaybeGetProxy(CilType fromType, CilType intoType, JavaCode code) { if (fromType.IsArray || object.ReferenceEquals(fromType, GenericArrayType) || fromType.Equals(JavaType.StringType)) { if (GenericUtil.ShouldCallGenericCast(fromType, intoType)) { code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType, GetProxyMethod); return(true); } } return(false); }
public static CilType LoadStaticData(CilType fldClass, JavaCode code) { LoadMaybeGeneric(fldClass, code); code.StackMap.PopStack(CilMain.Where); code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType, new JavaMethodRef("GetStatic", JavaType.ObjectType, CilType.SystemTypeType)); var returnType = PushStaticDataType(fldClass, code); code.NewInstruction(0xC0 /* checkcast */, returnType, null); return(returnType); }
void PopObjectAndLoadFromSpan(CilType fldClass) { var stackTop = stackMap.PopStack(CilMain.Where); stackMap.PushStack(stackTop); if (fldClass.IsValueClass && CodeSpan.LoadStore(true, (CilType)stackTop, null, fldClass, code)) { stackMap.PopStack(CilMain.Where); code.NewInstruction(0xC0 /* checkcast */, fldClass, null); } // pop object reference stackMap.PopStack(CilMain.Where); }
public static CilType MakeSpanOf(CilType fromType) { if (!fromType.IsPointer) { throw new ArgumentException(); } var newType = CodeSpan.SpanType.Clone(); newType.Flags |= VALUE; // we add the original buffer type as a generic parameter, // but we do not mark with HAS_GEN_PRM HasGenericParameters, // similar to WrapMethodGenericParameter newType.GenericParameters = new List <CilType>(); newType.GenericParameters.Add(fromType); return(newType); }
static CilInterface ImportPlainInterface(CilType interfaceType, List <CilInterface> list) { foreach (var ifc in list) { if (ifc.InterfaceType.JavaName == interfaceType.JavaName && ifc.GenericTypes == null) { return(ifc); } } var myInterface = new CilInterface(); myInterface.InterfaceType = interfaceType; return(myInterface); }
public static void BuildGenericProxy(CilInterfaceMethod ifcMethod, string methodSuffix, CilType intoType, List <CilInterfaceMethod> classMethods, JavaClass ifcClass) { CilMethod targetMethod = null; //Console.WriteLine("\n***** LOOKING FOR INTERFACE METHOD " + ifcMethod + " (SUFFIX " + methodSuffix + ") AKA " + ifcMethod.Method); foreach (var clsMethod in classMethods) { /*Console.WriteLine("> LOOKING AT " + (clsMethod.Method.IsExplicitImpl ? "EXPLICIT " : "") + "CLASS METHOD " + clsMethod + " AKA " + clsMethod.Method);*/ if (ifcMethod.GenericCompare(clsMethod)) { if (clsMethod.Method.IsExplicitImpl) { // a matching explicit override method is the best match, // and we can immediately stop searching targetMethod = clsMethod.Method; break; } else { // more than one method may match, if a derived type overrides // or hides a method that also exists in a base type. but the // derived (primary) type methods always come first. if (targetMethod == null) { targetMethod = clsMethod.Method; } } } } if (targetMethod == null) { throw CilMain.Where.Exception( $"missing method '{ifcMethod.Method}' " + $"(for interface '{ifcMethod.Method.DeclType}')"); } // Console.WriteLine("INTERFACE METHOD " + ifcMethod.Method + " TARGET " + targetMethod); BuildGenericProxy2(ifcMethod, targetMethod, true, intoType, ifcClass); }
public static void ValueCopy(CilType valueType, JavaCode code, bool swap = false) { // if 'from' value is pushed before 'into' object, call with swap == false // if 'into' object is pushed before 'from' value, call with swap == true if (valueType.IsGenericParameter) { if (swap) { code.NewInstruction(0x5F /* swap */, null, null); } else { // if storing a primitive value into a generic type, // and the generic type can be resolved to a primitive type, // then use a boxed-set method call var stackArray = code.StackMap.StackArray(); int stackArrayLen = stackArray.Length; if (stackArrayLen > 0 && (!stackArray[stackArrayLen - 1].IsReference)) { var genericMark = CilMain.GenericStack.Mark(); var(primitiveType, _) = CilMain.GenericStack.Resolve(valueType.JavaName); CilMain.GenericStack.Release(genericMark); if (!primitiveType.IsReference) { var boxedType = new BoxedType(primitiveType, false); code.NewInstruction(0xC0 /* checkcast */, boxedType, null); boxedType.SetValueVO(code); return; } } } code.NewInstruction(0xB8 /* invokestatic */, SystemGenericType, new JavaMethod("Copy", JavaType.VoidType, JavaType.ObjectType, JavaType.ObjectType)); } else { if (swap) { code.NewInstruction(0x5F /* swap */, null, null); } CilMethod.ValueMethod(CilMethod.ValueCopyTo, code); } }
public bool IsDerivedFrom(CilType otherBaseType) { var obj = this; for (;;) { if (obj.JavaName.Equals(otherBaseType.JavaName)) { return(true); } if (obj.SuperTypes == null || obj.SuperTypes.Count == 0) { return(false); } obj = obj.SuperTypes[0]; } }
void LoadStoreField(Code op, object data) { bool ok = false; if (data is FieldReference fieldRef) { var fldName = CilMain.MakeValidMemberName(fieldRef.Name); var fldClass = CilMain.GenericStack.EnterType(fieldRef.DeclaringType); var fldType = ValueUtil.GetBoxedFieldType(fldClass, fieldRef); if (fldClass.Equals(JavaType.StringType) || fldClass.Equals(JavaType.ThrowableType)) { // generally we translate System.String to java.lang.String, // and System.Exception to java.lang.Throwable, // but not in the case of a field reference fldClass = CilType.From(new JavaType(0, 0, fldClass.JavaName)); } bool isLoad = (op != Code.Stfld && op != Code.Stsfld); bool isStatic = (op == Code.Ldsfld || op == Code.Ldsflda || op == Code.Stsfld); bool isAddress = (op == Code.Ldflda || op == Code.Ldsflda); bool isVolatile = CheckVolatile(fldType); if (isLoad) { if (isAddress) { ok = LoadFieldAddress(fldName, fldType, fldClass, isStatic); } else { ok = LoadFieldValue(fldName, fldType, fldClass, isStatic, isVolatile); } } else { ok = StoreFieldValue(fldName, fldType, fldClass, isStatic, isVolatile); } } if (!ok) { throw new InvalidProgramException(); } }
public static CilType From(JavaType oldType) { var newType = new CilType(); newType.CopyFrom(oldType); if (newType.IsReference) { newType.JavaName = newType.ClassName; } else { string s; switch (newType.PrimitiveType) { case TypeCode.Empty: s = "system.Void"; break; case TypeCode.Boolean: s = "system.Boolean"; break; case TypeCode.Char: s = "system.Char"; break; case TypeCode.SByte: s = "system.SByte"; break; case TypeCode.Byte: s = "system.Byte"; break; case TypeCode.Int16: s = "system.Int16"; break; case TypeCode.UInt16: s = "system.UInt16"; break; case TypeCode.Int32: s = "system.Int32"; break; case TypeCode.UInt32: s = "system.UInt32"; break; case TypeCode.Int64: s = "system.Int64"; break; case TypeCode.UInt64: s = "system.UInt64"; break; case TypeCode.Single: s = "system.Single"; break; case TypeCode.Double: s = "system.Double"; break; default: throw new ArgumentException(); } newType.JavaName = s; } return(newType); }
static void LoadGeneric(CilType loadType, int loadIndex, JavaCode code) { if (loadIndex < 0) { if (code.Method.Class != null && (code.Method.Class .Flags & JavaAccessFlags.ACC_INTERFACE) != 0) { // a method compiled as part of an interface does not // have access to the generic-type member field throw CilMain.Where.Exception( "unsupported generic argument reference in interface method"); } // generic type is accessible through the generic-type member field code.NewInstruction(0x19 /* aload */, null, (int)0); code.NewInstruction(0xB4 /* getfield */, loadType, ConcreteTypeField); code.StackMap.PushStack(ConcreteTypeField.Type); code.NewInstruction(0x12 /* ldc */, null, -loadIndex - 1); code.StackMap.PushStack(JavaType.IntegerType); // call system.RuntimeType.Argument(RuntimeType runtimeType, int typeArgumentIndex) code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType, new JavaMethodRef("Argument", CilType.SystemTypeType, CilType.SystemRuntimeTypeType, JavaType.IntegerType)); code.StackMap.PopStack(CilMain.Where); // integer code.StackMap.PopStack(CilMain.Where); // generic type field code.StackMap.PushStack(CilType.SystemTypeType); // type result } else if (loadIndex > 0) { // generic type is accessible through a parameter code.NewInstruction(0x19 /* aload */, null, (int)(loadIndex - 1)); code.StackMap.PushStack(CilType.SystemTypeType); } else { // generic type is known to be a constant LoadMaybeGeneric(loadType, code); } }
static CilType FindCommonSuperType(CilType type1, CilType type2) { if (type1.SuperTypes != null && type2.SuperTypes != null) { foreach (var sup1 in type1.SuperTypes) { if (!sup1.Equals(JavaType.ObjectType)) { if (FindCommonSuperTypeRecursive(sup1, type2)) { return(sup1); } } } } return(null); }
static bool FindCommonSuperTypeRecursive(CilType sup1, CilType type2) { if (type2.SuperTypes != null) { foreach (var sup2 in type2.SuperTypes) { if (sup2.Equals(sup1)) { return(true); } if (FindCommonSuperTypeRecursive(sup1, sup2)) { return(true); } } } return(false); }
bool LoadFieldAddress(string fldName, CilType fldType, CilType fldClass, bool isStatic) { if (!(fldType is BoxedType)) { if (!fldType.IsValueClass) { throw CilMain.Where.Exception($"cannot load address of unboxed field '{fldName}'"); } } if (isStatic && fldClass.HasGenericParameters) { fldClass = LoadStaticData(fldClass); isStatic = false; } byte op; if (!isStatic) { PopObjectAndLoadFromSpan(fldClass); op = 0xB4; // getfield } else { op = 0xB2; // getstatic } code.NewInstruction(op, fldClass.AsWritableClass, new JavaFieldRef(fldName, fldType)); if (fldType is ThreadBoxedType tlsType) { tlsType.GetInnerObject(code); } if (fldType.IsGenericParameter) { fldType = GenericUtil.CastMaybeGeneric(fldType, true, code); } stackMap.PushStack(fldType); return(true); }