private ArrayJavaType(string repr, string jniTypeSignature, JavaType elementType, IEnumerable <string> annotations) : base(annotations) { Repr = repr; JniTypeSignature = jniTypeSignature; ElementType = elementType; }
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); } }
static TypeCode GetNumericTypeCode(JavaType type) { if (type.IsReference) { string boxed = (type is BoxedType) ? "boxed " : ""; throw new ArgumentException($"{boxed}type '{type}' is not compatible with numeric operation"); } switch (type.PrimitiveType) { case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Char: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Boolean: return(TypeCode.Int32); case TypeCode.Int64: case TypeCode.UInt64: return(TypeCode.Int64); case TypeCode.Single: case TypeCode.Double: return(type.PrimitiveType); default: throw new InvalidProgramException(); } }
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; int localIndex = locals.GetTempIndex(stackTop); TestAndCast(code, castClass, stackTop, nextLabel, localIndex); locals.FreeTempIndex(localIndex); } }
public static JavaPackage[] Parse(XElement metadataElement) { return(metadataElement.Elements("package") .Select(xPackage => new JavaPackage { Name = xPackage.Attribute("name").Value, Types = xPackage.Elements() .Where(xType => JavaType.IsValid(xType.Name.LocalName)) .Select(xType => new JavaType { Name = xType.Attribute("name").Value, Kind = xType.Name.LocalName, Visibility = xType.Attribute("visibility").Value, Members = xType.Elements() .Where(xMember => JavaMember.IsValid(xMember.Name.LocalName)) .Select(xMember => new JavaMember { Name = xMember.Attribute("name").Value, Kind = xMember.Name.LocalName, Visibility = xMember.Attribute("visibility").Value, Parameters = xMember.Elements("parameter") .Select(xParameter => new JavaParameter { Name = xParameter.Attribute("name").Value, Type = xParameter.Attribute("type").Value }) .ToArray() }) .ToArray() }) .ToArray() }) .ToArray()); }
protected JavaType GetBaseClass(JavaType cls) { var name = cls.ClassName; if (IsBoxedIntPtr || name == "system.UInt64") { // IntPtr, UIntPtr, UInt64 -> Int64 name = "system.Int64"; } else if (name == "system.UInt32") { name = "system.Int32"; } else if (name == "system.UInt16") { name = "system.Int16"; } else if (name == "system.Byte") { name = "system.SByte"; } else { return(cls); } return(new JavaType(0, 0, name)); }
static byte TestBool(JavaCode code, JavaType stackTop) { if (stackTop.IsReference) { return(0xC7); // ifnonnull } if (stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64 || 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) { if (stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64) { code.NewInstruction(0x09 /* lconst_0 (long) */, null, null); code.NewInstruction(0x94 /* lcmp (long) */, null, null); } return(0x9A); // ifne != zero } throw new InvalidProgramException(); }
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 Address(CilType fromType, CilType intoType, JavaCode code) { if (intoType.Equals(SpanType) && (!fromType.Equals(SpanType))) { // allow assignment of null to clear the pointer if (fromType.Equals(JavaStackMap.Null)) { return(true); } // allow assignment of native int (presumably zero) bool callAssign = false; bool pushNullType = true; JavaType argType = fromType; JavaType retType = SpanType; if ((!fromType.IsReference) && fromType.PrimitiveType == TypeCode.UInt64) { callAssign = true; } else if (intoType.GenericParameters != null) { // allow assignment when the types match callAssign = intoType.GenericParameters[0].Equals(fromType) || fromType.JavaName == intoType.GenericParameters[0].JavaName; // for arbitrary value types, call a Assign(ValueType) if (fromType.IsValueClass) { argType = retType = CilType.SystemValueType; GenericUtil.LoadMaybeGeneric(fromType, code); pushNullType = false; } } if (callAssign) { if (pushNullType) { code.NewInstruction(0x01 /* aconst_null */, null, null); code.StackMap.PushStack(CilType.SystemTypeType); } code.NewInstruction(0xB8 /* invokestatic */, SpanType, new JavaMethodRef("Assign" + CilMain.EXCLAMATION, retType, argType, CilType.SystemTypeType)); code.NewInstruction(0xC0 /* checkcast */, SpanType, null); code.StackMap.PopStack(CilMain.Where); // null type return(true); } throw new Exception($"bad assignment of '{fromType.JavaName}' into pointer of '{intoType.GenericParameters[0].JavaName}'"); } return(false); }
public JavaType GetInnerObject(JavaCode code) { var innerType = new JavaType(0, 0, OldClassName); code.NewInstruction(0xB6 /* invokevirtual */, this, new JavaMethodRef("get", JavaType.ObjectType)); code.NewInstruction(0xC0 /* checkcast */, innerType, null); return(UnboxedType.IsEnum ? SystemEnumType : innerType); }
static byte TestEq(JavaCode code, JavaType stackTop, JavaType stackTop2, Mono.Cecil.Cil.Instruction cilInst) { if (stackTop.IsReference || stackTop2.IsReference) { byte cmpOp = CodeSpan.CompareEq(stackTop, stackTop2, cilInst, code); if (cmpOp == 0) { cmpOp = 0xA5; // if_acmpeq (reference) } return(cmpOp); } if (stackTop2.IsIntLike && (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(0x9F); // if_icmpeq } byte op; if ((stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64) && (stackTop2.PrimitiveType == TypeCode.Int64 || stackTop2.PrimitiveType == TypeCode.UInt64)) { op = 0x94; // lcmp (long) } else if (stackTop.PrimitiveType == TypeCode.Single && stackTop2.PrimitiveType == TypeCode.Single) { op = 0x95; // fcmpl (float) } else if (stackTop.PrimitiveType == TypeCode.Double && stackTop2.PrimitiveType == TypeCode.Double) { op = 0x97; // dcmpl (double) } else { throw new Exception($"incompatible types '{stackTop}' and '{stackTop2}'"); } code.NewInstruction(op, null, null); return(0x99); // ifeq == zero }
public ArrayJavaType(JavaType elementType) { if (elementType.Kind == JavaTypeKind.Void) { throw new ArgumentException("Element type is void.", nameof(elementType)); } ElementType = elementType; Repr = elementType.AsString + "[]"; JniTypeSignature = "[" + elementType.JniTypeSignature; }
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); }
internal static NativeValue ToNativeValue(this object source, JavaRuntime runtime) { JavaType jt = source.GetType().ToJniSignature(); if (jt != null) { return(jt.ToNativeValue(runtime, source)); } return(new NativeValue()); }
internal static void MakeRoomForCategory2ValueOnStack(JavaCode code, JavaType prev = null) { // ensure the stack has enough space for a category-2 value // following a value of either category-1 or category-2 if (code.StackMap != null) { code.StackMap.PushStack(prev ?? JavaType.IntegerType); code.StackMap.PushStack(JavaType.LongType); code.StackMap.PopStack(CilMain.Where); code.StackMap.PopStack(CilMain.Where); } }
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 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);
IEnumerable <ApiComparisonReport> CompareImplements(JavaType rtype, JavaType ttype) { foreach (var rImpl in rtype.Implements) { if (ttype.Implements.All(_ => _.Name != rImpl.Name)) { yield return new ApiComparisonReport { Context = rtype, Issue = ApiComparisonIssue.MissingInterfaceImplementation, Message = $"`{ttype.FullName}` does not implement interface `{rImpl.Name}`." } } } ; }
protected internal virtual object deserializeJsonObject(string className, sbyte[] data) { try { JavaType type = TypeFactory.defaultInstance().constructFromCanonical(className); return(objectMapper.readValue(StringHelper.NewString(data, Charset.forName("UTF-8")), type)); } catch (Exception e) { throw new InvalidRequestException(Response.Status.INTERNAL_SERVER_ERROR, "Could not deserialize JSON object: " + e.Message); } }
static void ConvertReference(JavaCode code, JavaType oldType, TypeCode newType) { if (newType == TypeCode.Int64 || newType == TypeCode.UInt64) { // in CIL code, it is typical to see a load address instruction // followed by 'conv.u'. we just ignore and keep the original type code.NewInstruction(0x00 /* nop */, null, null); code.StackMap.PushStack(oldType); } else { throw new InvalidProgramException(); } }
public int GetTempIndex(JavaType type) { int index = nextTempIndex; stackMap.SetLocal(index, type); nextTempIndex += type.Category; if (nextTempIndex > maxTempIndex) { maxTempIndex = nextTempIndex; } return(index); }
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); }
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); }
TypeReference CilTypeReference(JavaType jtype) { string typeName = jtype.ClassName; if (typeName == null) { typeName = "./" + jtype.PrimitiveType; } if (typeMap.TryGetValue(typeName, out var cilType)) { CilTypeAddUse(cilType); if (jtype.ArrayRank != 0) { cilType = new ArrayType(cilType, jtype.ArrayRank); } return(cilType); } if (typeName.IndexOf('$') == -1) { Console.WriteLine($"auto-generating empty class for '{typeName}'"); string nsName, clsName; int dot = typeName.LastIndexOf('.'); if (dot == -1 || dot + 1 == typeName.Length) { nsName = null; clsName = typeName; } else { nsName = typeName.Substring(0, dot - 1); clsName = typeName.Substring(dot + 1); } cilType = new TypeDefinition(nsName, clsName, TypeAttributes.Public); CilTypeAddUse(cilType); typeMap[typeName] = cilType; module.Types.Add(cilType as TypeDefinition); return(cilType); } throw new JavaException($"unknown type '{typeName}'", Where); }
public void Visit(Document document) { foreach (var definition in document.Definitions) { var javaType = new JavaType(documentContext.Namespace, TemplateContextGenerator.MangleJavaTypeName(definition.Name), javaNamespace); if (definition is Struct) { javaType.IsLeanStruct = true; } else if (definition is IntegerEnum) { javaType.IsLeanEnum = true; } LOG.Debug(string.Format("Registering type '{0}'", javaType)); documentContext.TypeRegistry.Add(javaType); } }
internal T InvokeMethod <T>(IntPtr id, IntPtr methodId, NativeValue[] parameters, bool isStatic) { Type type = typeof(T); if (type == typeof(object) || type == typeof(JObject) || type == typeof(string)) // We need to read string as it is the object. { var objectCaller = this.MethodCallers.Where(call => call is MethodCaller <IntPtr>).FirstOrDefault(); if (objectCaller != null) { var methodCaller = objectCaller as MethodCaller <IntPtr>; IntPtr pointer = methodCaller.Invoke(id, methodId, parameters, isStatic); // For string we need to read it. if (type == typeof(string)) { string str = this.Gateway.Runtime.JavaEnvironment.ReadJavaString(pointer); return((T)(object)str); } JavaType javaType = JavaMapper.GetRegisteredJavaTypes().Where(jt => jt.CSharpType == type).FirstOrDefault(); if (javaType != null) { IntPtr javaClass = this.Gateway.Runtime.JavaEnvironment.JNIEnv.GetObjectClass(pointer); return((T)(object)new JObject(this.Gateway, javaType.JavaTypeName, javaClass, pointer)); } } } else { var callers = this.MethodCallers.Where(call => call is MethodCaller <T>); var caller = callers.FirstOrDefault(); if (caller != null) { return((caller as MethodCaller <T>).Invoke(id, methodId, parameters, isStatic)); } } return(default(T)); }
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); }
private T ReturnValue <T>(IntPtr id, string name, Func <IntPtr, string, string, T> GetId) { if (GetId == null) { return(default(T)); } try { Type retType = typeof(T); JavaType sigType = retType.ToJniSignature(); string jniSignature = sigType.JniField; return(GetId(id, name, jniSignature)); } catch { throw new ArgumentException(this.Runtime.JavaEnvironment.CatchJavaException()); } }
internal static JavaType ToJniSignature(this Type type) { if (type.IsArray) { return(null); } // Try to get primitive type JavaType jt = JavaMapper.GetRegisteredJavaTypes().Where(javaType => javaType.CSharpType == type).FirstOrDefault(); if (jt != null) { return(jt); } string typeName = type.FullName; string jniTypeName = typeName.Replace(".", "/"); jt = new JavaType(typeName, typeName.ToJniSignatureString(), type); return(jt); }
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); }