public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // find the ClassReference object object targetObject = property.serializedObject.targetObject; string field = property.propertyPath; ClassReference reference = this.GetFieldValue(targetObject, field) as ClassReference; // get the types that inherit from the requested type and their names Type[] types; String[] names; this.GetValidTypesFor(reference.GetRequiredType(), out types, out names); // Find the index of the selected type in the array of available types or set the index to zero if not found. // No need to remember the index since Unity will use this PropertyDrawer multiple times for different fields. int selectedIndex = this.FindTypeIndex(types, reference.ReferencedClassType); if (selectedIndex < 0) { selectedIndex = 0; reference.ReferencedClassType = null; } // draw the label and the combobox label = EditorGUI.BeginProperty(position, label, property); Rect comboboxPosition = EditorGUI.PrefixLabel(position, label); int selected = EditorGUI.Popup(comboboxPosition, selectedIndex, names); if (selected != selectedIndex) { reference.ReferencedClassType = types[selected]; } EditorGUI.EndProperty(); }
/// <summary> /// Default ctor /// </summary> private BoxInfo(XTypeReferenceKind metadataType, ClassReference boxedClass, PrimitiveType primitiveType, string unboxMethodName, RCode convertAfterCode) { this.metadataType = metadataType; this.boxedClass = boxedClass; this.primitiveType = primitiveType; this.unboxMethodName = unboxMethodName; this.convertAfterCode = convertAfterCode; }
public int GetClassIndex(ClassReference reference) { var classInfo = new ClassInfo((ushort)GetUtf8Index(reference.Name)); if (!_classInfos.TryGetValue(classInfo, out int index)) { index = AddConstant(classInfo); _classInfos.Add(classInfo, index); } return(index); }
/// <summary> /// Execute an expression /// </summary> /// <param name="expression">The expression to interpret</param> /// <returns>Returns the returned value of the expression</returns> internal object RunExpression(AlgorithmExpression expression) { object result = null; switch (expression.DomType) { case AlgorithmDomType.PrimitiveExpression: result = new PrimitiveValue(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.PropertyReferenceExpression: result = new PropertyReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.VariableReferenceExpression: result = new VariableReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.ClassReferenceExpression: result = new ClassReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.ThisReferenceExpression: result = new ThisReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.InstanciateExpression: result = new Instanciate(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.InvokeCoreMethodExpression: result = new InvokeCoreMethod(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.InvokeMethodExpression: result = new InvokeMethod(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.BinaryOperatorExpression: result = new BinaryOperator(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.ArrayIndexerExpression: result = new ArrayIndexerExpression(DebugMode, this, expression).Execute(); break; default: ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new InvalidCastException($"Unable to find an interpreter for this expression : '{expression.GetType().FullName}'"), expression), GetDebugInfo())); break; } return(FailedOrStop ? null : result); }
public JavaClassFile CreateClassFile(JavaClassImage image) { var context = new BuildingContext(this); // Basic structure. var file = new JavaClassFile { MajorVersion = image.MajorVersion, MinorVersion = image.MinorVersion, }; var thisReference = new ClassReference(image.RootClass.Name); file.ThisClass = (ushort)ConstantPoolBuffer.GetClassIndex(thisReference); if (image.RootClass.SuperClass != null) { file.SuperClass = (ushort)ConstantPoolBuffer.GetClassIndex(image.RootClass.SuperClass); } file.AccessFlags = image.RootClass.AccessFlags; // Fields foreach (var field in image.RootClass.Fields) { file.Fields.Add(CreateFieldInfo(context, field)); } // Methods foreach (var method in image.RootClass.Methods) { file.Methods.Add(CreateMethodInfo(context, method)); } // Source file if (image.SourceFile != null) { file.Attributes.Add(CreateAttribute(context, new SingleIndexAttribute( SingleIndexAttribute.SourceFileAttribute, (ushort)ConstantPoolBuffer.GetUtf8Index(image.SourceFile)))); } if (BootstrapMethodsAttribute.BootstrapMethods.Count > 0) { file.Attributes.Add(CreateAttribute(context, BootstrapMethodsAttribute)); } AddAttributes(context, file, image); file.ConstantPool = ConstantPoolBuffer.CreateConstantPool(); return(file); }
private void Remove(ClassReference classReference) { var entity = entities.Buffer[classReference.Index]; if (references.UnorderedRemoveAt(classReference.Index)) { references[classReference.Index].Index = classReference.Index; } entities.UnorderedRemoveAt(classReference.Index); classReference.Child?.ClassEntityCollection.RemoveBlind(classReference.Child); classReference.Clear(); referencePool.Add(classReference); Removed?.Invoke(entity); }
private ClassReference ConvertClassReference(ClassReference sourceRef, AssemblyCompiler compiler, DexTargetPackage targetPackage) { TypeEntry type = _map.GetTypeBySignature(sourceRef.Descriptor); if (IsDelegateInstance(type)) { // special delegate handling. return(GetDelegateInstanceType(type, sourceRef, compiler, targetPackage).InstanceDefinition); } else { var xTypeDef = ResolveToType(type, sourceRef, compiler); return(xTypeDef.GetClassReference(targetPackage)); } }
/// <summary> /// Create the current type as class definition. /// </summary> internal DelegateInstanceTypeBuilder( ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, ClassDefinition delegateClass, XMethodDefinition invokeMethod, Prototype invokePrototype, XMethodDefinition calledMethod) { this.sequencePoint = sequencePoint; this.compiler = compiler; this.targetPackage = targetPackage; this.delegateClass = delegateClass; this.invokeMethod = invokeMethod; this.invokePrototype = invokePrototype; this.calledMethod = calledMethod; this.multicastDelegateClass = compiler.GetDot42InternalType("System", "MulticastDelegate").GetClassReference(targetPackage); }
private ClassReference GetReference() { ClassReference reference = null; if (referencePool.Count > 0) { reference = referencePool.Buffer[referencePool.Count - 1]; referencePool.Buffer[referencePool.Count - 1] = null; --referencePool.Count; } else { reference = new ClassReference(); } reference.Collection = this; return(reference); }
public void BuildSimpleHelloWorld() { // Create main method. var mainMethod = new MethodDefinition("main", new MethodDescriptor(BaseType.Void, ObjectType.String.CreateArrayType())) { AccessFlags = MethodAccessFlags.Public | MethodAccessFlags.Static, }; // Build references. var printStream = new ClassReference("java/io/PrintStream"); var systemOut = new FieldReference("out", new ClassReference("java/lang/System"), new FieldDescriptor(new ObjectType("java/io/PrintStream"))); var println = new MethodReference("println", printStream, new MethodDescriptor(BaseType.Void, ObjectType.String)); // Build body. mainMethod.Body = new ByteCodeMethodBody { Variables = { new LocalVariable("args", new FieldDescriptor(mainMethod.Descriptor.ParameterTypes[0])) }, Instructions = { new ByteCodeInstruction(ByteOpCodes.GetStatic, systemOut), new ByteCodeInstruction(ByteOpCodes.Ldc, "Hello, world!"), new ByteCodeInstruction(ByteOpCodes.InvokeVirtual, println), new ByteCodeInstruction(ByteOpCodes.Return) } }; mainMethod.Body.Variables[0].Start = mainMethod.Body.Instructions[0]; // Create container class. var classDef = new ClassDefinition("HelloWorld") { Methods = { mainMethod }, SuperClass = new ClassReference("java/lang/Object"), }; var classImage = new JavaClassImage(classDef); // Verify. _fixture.BuildAndVerifyOutput(classImage, "Hello, world!" + Environment.NewLine); }
private dynamic ClassRefDo(ClassReference classReference) { var oldSpace = MemorySpaces.Current; var memorySpace = Get(classReference.ClassInstance).Value as MemorySpace; MemorySpaces.Current = memorySpace; try { if (classReference.Deferences.Count == 0) { return(memorySpace); } foreach (var deref in classReference.Deferences) { // make sure that the last dereference knows how to pull // its arguments, which are from the original memory space and not // the relative class space. i.e. A.b.foo(x), x is loaded from the // space that contains A, not from the space of b. if (deref == classReference.Deferences.Last()) { deref.CallingMemory = oldSpace; } var newSpace = GetValue(Exec(deref)); if (deref == classReference.Deferences.Last()) { return(newSpace); } MemorySpaces.Current = newSpace; } } finally { MemorySpaces.Current = oldSpace; } return(null); }
public override void Execute(Context context) { foreach (MethodDefinition method in context.Class.Methods.ToArray()) { if (context.Engine.UntouchableMethods.Contains(method)) { continue; } for (int i = 0; i < method.Body.Instructions.Count; i++) { ByteCodeInstruction byteCodeInstruction = method.Body.Instructions[i]; if (byteCodeInstruction.OpCode.Equal(ByteOpCodes.Ldc)) { object operand = byteCodeInstruction.Operand; Type operandType = operand.GetType(); if (operandType == typeof(string)) { string value = (string)operand; string encodedValue = Encode(value); var newString = new ClassReference("java/lang/String"); var getDecoder = new MethodReference("getDecoder", new ClassReference("java/util/Base64"), new MethodDescriptor(new ObjectType("java/util/Base64$Decoder"))); var decode = new MethodReference("decode", new ClassReference("java/util/Base64$Decoder"), new MethodDescriptor(new ArrayType(new BaseType(BaseTypeValue.Byte)), ObjectType.String)); var initString = new MethodReference("<init>", new ClassReference("java/lang/String"), new MethodDescriptor(BaseType.Void, new ArrayType(new BaseType(BaseTypeValue.Byte)))); method.Body.Instructions[i] = new ByteCodeInstruction(ByteOpCodes.New, newString); method.Body.Instructions.Insert(i + 1, new ByteCodeInstruction(ByteOpCodes.Dup)); method.Body.Instructions.Insert(i + 2, new ByteCodeInstruction(ByteOpCodes.InvokeStatic, getDecoder)); method.Body.Instructions.Insert(i + 3, new ByteCodeInstruction(ByteOpCodes.Ldc, encodedValue)); method.Body.Instructions.Insert(i + 4, new ByteCodeInstruction(ByteOpCodes.InvokeVirtual, decode)); method.Body.Instructions.Insert(i + 5, new ByteCodeInstruction(ByteOpCodes.InvokeSpecial, initString)); i += 5; } } } } }
/// <summary> /// Create the body of the equals method. /// </summary> private static MethodBody CreateEqualsCheckTypeOnlyBody(ClassReference delegateClass) { MethodBody body = new MethodBody(null); // This pointer and method argument. Register rthis = body.AllocateRegister(RCategory.Argument, RType.Object); Register rother = body.AllocateRegister(RCategory.Argument, RType.Object); // result register Register result = body.AllocateRegister(RCategory.Temp, RType.Value); var ins = body.Instructions; // Check if other object can be casted. ins.Add(new Instruction(RCode.Instance_of, delegateClass, new[] { result, rother })); // Add return instructions ins.Add(new Instruction(RCode.Return, result)); return(body); }
/// <summary> /// Delegate methods are created unfortunately during the compilation phase in AstCompiler.VisitExpression. /// Model this behaviour here. /// </summary> private DelegateInstanceType GetDelegateInstanceType(TypeEntry typeEntry, ClassReference classRef, AssemblyCompiler compiler, DexTargetPackage targetPackage) { var scopeIds = typeEntry.ScopeId.Split(new[] { ":delegate:" }, StringSplitOptions.None); var typeScopId = scopeIds[0]; var xTypeDef = compiler.Module.GetTypeByScopeID(GetTypeScopeId(typeEntry.Scope, typeScopId, typeEntry.Name)); var delegateType = compiler.GetDelegateType(xTypeDef); var calledMethodId = scopeIds[1]; var calledTypeScopeId = calledMethodId.Split('|')[0]; var calledMethodScope = calledMethodId.Split('|')[1]; var calledTypeDef = compiler.Module.GetTypeByScopeID(calledTypeScopeId); var calledMethod = calledTypeDef.GetMethodByScopeId(calledMethodScope); // NOTE: we are loosing the SequencePoint (DebugInfo) here. I'm not sure if this // was ever valuable anyways. var delInstanceType = delegateType.GetOrCreateInstance(null, targetPackage, calledMethod); return(delInstanceType); }
/// <summary> /// will throw if type is not found. /// </summary> private static XTypeDefinition ResolveToType(TypeEntry type, ClassReference sourceRef, AssemblyCompiler compiler) { XTypeDefinition xTypeDef = null; if (type != null) { string scopeId = GetTypeScopeId(type); xTypeDef = compiler.Module.GetTypeByScopeID(scopeId); } else { string scopeId = sourceRef.Descriptor.Substring(1, sourceRef.Descriptor.Length - 2); xTypeDef = compiler.Module.GetTypeByScopeID(scopeId); } if (xTypeDef == null) { throw new CompilerCacheResolveException("unable to resolve " + sourceRef); } return(xTypeDef); }
// Generally this is used with the name resolver. So for example, you have a refernce to a ClassDefinition // instance from the resolver, but you want to turn it into a ClassReference instance. // TODO: put this in a method on these classes and implement an interface. The function signatures are all close enough. public static Expression ConvertStaticReferenceToExpression(TopLevelEntity item, Token primaryToken, Node owner) { Expression output = null; TopLevelEntity referencedEntity = null; if (item is ClassDefinition) { ClassDefinition classDef = (ClassDefinition)item; output = new ClassReference(primaryToken, classDef, owner); referencedEntity = classDef; } else if (item is EnumDefinition) { EnumDefinition enumDef = (EnumDefinition)item; output = new EnumReference(primaryToken, enumDef, owner); referencedEntity = enumDef; } else if (item is ConstDefinition) { ConstDefinition constDef = (ConstDefinition)item; output = new ConstReference(primaryToken, constDef, owner); referencedEntity = constDef; } else if (item is FunctionDefinition) { FunctionDefinition funcDef = (FunctionDefinition)item; output = new FunctionReference(primaryToken, funcDef, owner); referencedEntity = funcDef; } else { throw new InvalidOperationException(); } Node.EnsureAccessIsAllowed(primaryToken, owner, referencedEntity); return(output); }
public ReadOnlyClassReference(ClassReference classReference) { genericParameters = classReference.GenericParameters.ToArray(parameter => new ReadOnlyTypeReference(parameter)); if (!string.IsNullOrWhiteSpace(classReference.TypeText)) { name = classReference.TypeText; } else if (classReference.Class != null) { name = classReference.Class.Name; } else if (classReference.ClassNestedClass != null) { name = classReference.ClassNestedClass.Name; } else if (classReference.StructNestedClass != null) { name = classReference.StructNestedClass.Name; } else if (classReference.Type != null) { name = classReference.Type.Name; } }
public int GetClassIndex(ClassReference reference) { return(_buffer.GetClassIndex(reference)); }
public virtual void Collect(ClassReference @class) { Collect(@class as TypeReference); }
private dynamic Expression(Expr ast) { var lhs = ast.Left; var rhs = ast.Right; switch (ast.Token.TokenType) { case TokenType.Equals: if (lhs.AstType == AstTypes.ClassRef) { // a litle trickery here. create a copy of the class reference // with everytihng up to the second to last item. this gives you // the workign memory space that the very last item should sit in // then lets execute this as if we are asking for the memory space // and finally assign the very last symbol to the calculated memory // space we got var classRef = (lhs as ClassReference); var lastItem = classRef.Deferences.Last(); var fakeRef = new ClassReference(classRef.ClassInstance, classRef.Deferences.Take(classRef.Deferences.Count - 1) .ToList()); var space = GetValue(Exec(fakeRef)); Assign(lastItem, Exec(rhs), space); } else { ValueMemory itemSpace = Get(lhs); Assign(lhs, Exec(rhs), itemSpace != null ? itemSpace.Memory : null); } return(null); case TokenType.Word: return(Get(ast)); case TokenType.Int: return(Convert.ToInt32(ast.Token.TokenValue)); case TokenType.Float: return(Convert.ToDouble(ast.Token.TokenValue)); case TokenType.QuotedString: return(ast.Token.TokenValue); case TokenType.Nil: return(TokenType.Nil); case TokenType.True: return(true); case TokenType.False: return(false); } if (TokenUtil.IsOperator(ast.Token)) { return(ApplyOperation(ast)); } return(null); }
public void Visit(ClassReference ast) { throw new NotImplementedException(); }
public void Visit(ClassReference ast) { Exec(ast); }
public int GetClassIndex(ClassReference reference) { return(_builder.ConstantPoolBuffer.GetClassIndex(reference)); }
private static void AddGenericParameterArguments(Prototype result, bool buildAsArray, int numParameters, string parameterBaseName, ClassReference annType, IList <Parameter> parameterArray) { if (buildAsArray) { // Add GenericInstance parameter (to pass the generic instance array of the declaring type) var paramType = FrameworkReferences.ClassArray; var dparameter = new Parameter(paramType, parameterBaseName); dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime)); result.Parameters.Add(dparameter); parameterArray.Add(dparameter); } else { for (int i = 0; i < numParameters; ++i) { var dparameter = new Parameter(FrameworkReferences.Class, parameterBaseName + (i + 1)); dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime)); result.Parameters.Add(dparameter); parameterArray.Add(dparameter); } } }
/// <summary> /// Create the body of the equals method. /// </summary> private static MethodBody CreateEqualsBody(ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, XMethodDefinition equalsMethod, Prototype equalsPrototype, FieldDefinition instanceField, ClassReference delegateClass) { MethodBody body = new MethodBody(null); // This pointer and method argument. Register rthis = body.AllocateRegister(RCategory.Argument, RType.Object); Register rother = body.AllocateRegister(RCategory.Argument, RType.Object); // Create code. var ins = body.Instructions; // Temporary parameter result. Register result = body.AllocateRegister(RCategory.Temp, RType.Value); // Prepare the return instruction. Instruction returnInstruction = new Instruction(RCode.Return, result); // Check if other object can be casted. ins.Add(new Instruction(RCode.Instance_of, delegateClass, new[] { result, rother })); ins.Add(new Instruction(RCode.If_eqz, returnInstruction, new[] { result })); // compare instance members // Cast of the other object. ins.Add(new Instruction(RCode.Check_cast, delegateClass, new[] { rother })); // Get instance fields of this and other. var thisInstance = body.AllocateRegister(RCategory.Temp, RType.Object); var otherInstance = body.AllocateRegister(RCategory.Temp, RType.Object); // Load the instance fields. ins.Add(new Instruction(RCode.Iget_object, thisInstance, rthis) { Operand = instanceField }); ins.Add(new Instruction(RCode.Iget_object, otherInstance, rother) { Operand = instanceField }); // Compare the instance fields. ins.Add(new Instruction(RCode.If_eq, returnInstruction, new[] { thisInstance, otherInstance })); // compare instance members // Set result to false if not equal. ins.Add(new Instruction(RCode.Const, 0, new[] { result })); // Add return instructions ins.Add(returnInstruction); return(body); }
/// <summary> /// Create the body of the invoke method. /// </summary> private static MethodBody CreateInvokeBody(ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, XMethodDefinition calledMethod, XMethodDefinition invokeMethod, Prototype invokePrototype, Prototype calledMethodPrototype, FieldDefinition instanceField, ClassReference delegateClass) { var body = new MethodBody(null); var rthis = body.AllocateRegister(RCategory.Argument, RType.Object); foreach (var p in invokePrototype.Parameters) { if (p.Type.IsWide()) { body.AllocateWideRegister(RCategory.Argument); } else { var type = (p.Type is PrimitiveType) ? RType.Value : RType.Object; body.AllocateRegister(RCategory.Argument, type); } } var incomingMethodArgs = body.Registers.ToArray(); // Create code var ins = body.Instructions; Register instance = null; if (!calledMethod.IsStatic) { // load instance instance = body.AllocateRegister(RCategory.Temp, RType.Object); ins.Add(new Instruction(RCode.Iget_object, instance, rthis) { Operand = instanceField }); } // Invoke var calledMethodRef = calledMethod.GetReference(targetPackage); var inputArgs = calledMethod.IsStatic ? incomingMethodArgs.Skip(1).ToArray() : incomingMethodArgs; // Cast arguments (if needed) var outputArgs = new List <Register>(); if (!calledMethod.IsStatic) { outputArgs.Add(instance); } var parameterIndex = 0; for (var i = calledMethod.IsStatic ? 0 : 1; i < inputArgs.Length;) { var invokeType = invokePrototype.Parameters[parameterIndex].Type; var inputIsWide = invokeType.IsWide(); var calledType = calledMethodPrototype.Parameters[parameterIndex].Type; if (!invokeType.Equals(calledType)) { // Add cast / unbox var source = inputIsWide ? new RegisterSpec(inputArgs[i], inputArgs[i + 1], invokeType) : new RegisterSpec(inputArgs[i], null, invokeType); var tmp = ins.Unbox(sequencePoint, source, calledMethod.Parameters[parameterIndex].ParameterType, compiler, targetPackage, body); outputArgs.Add(tmp.Result.Register); if (calledType.IsWide()) { outputArgs.Add(tmp.Result.Register2); } } else { outputArgs.Add(inputArgs[i]); if (calledType.IsWide()) { outputArgs.Add(inputArgs[i + 1]); } } i += inputIsWide ? 2 : 1; parameterIndex++; } // Actual call ins.Add(new Instruction(calledMethod.Invoke(calledMethod, null), calledMethodRef, outputArgs.ToArray())); // Collect return value var invokeReturnType = invokePrototype.ReturnType; var calledReturnType = calledMethodPrototype.ReturnType; var needsBoxing = !invokeReturnType.Equals(calledReturnType); Instruction returnInstruction; if (calledReturnType.IsWide()) { var r = body.AllocateWideRegister(RCategory.Temp); ins.Add(new Instruction(RCode.Move_result_wide, r.Item1)); if (needsBoxing) { // Box var source = new RegisterSpec(r.Item1, r.Item2, calledReturnType); var tmp = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body); returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register); } else { // Return wide returnInstruction = new Instruction(RCode.Return_wide, r.Item1); } } else if (calledMethod.ReturnType.IsVoid()) { // Void return returnInstruction = new Instruction(RCode.Return_void); } else if (calledReturnType is PrimitiveType) { // Single register return var r = body.AllocateRegister(RCategory.Temp, RType.Value); ins.Add(new Instruction(RCode.Move_result, r)); if (needsBoxing) { // Box var source = new RegisterSpec(r, null, invokeReturnType); var tmp = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body); returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register); } else { // Return returnInstruction = new Instruction(RCode.Return, r); } } else { var r = body.AllocateRegister(RCategory.Temp, RType.Object); ins.Add(new Instruction(RCode.Move_result_object, r)); if (needsBoxing) { // Box var source = new RegisterSpec(r, null, invokeReturnType); var tmp = ins.Box(sequencePoint, source, invokeMethod.ReturnType, targetPackage, body); returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register); } else { // Return returnInstruction = new Instruction(RCode.Return_object, r); } } // Call next delegate (if any) var next = body.AllocateRegister(RCategory.Temp, RType.Object); var multicastDelegateType = new ClassReference(targetPackage.NameConverter.GetConvertedFullName("System.MulticastDelegate")); var nextReference = new FieldReference(multicastDelegateType, "next", multicastDelegateType); ins.Add(new Instruction(RCode.Iget_object, nextReference, new[] { next, rthis })); // load this.next var afterCallNext = new Instruction(RCode.Nop); ins.Add(new Instruction(RCode.If_eqz, afterCallNext, new[] { next })); // if next == null, continue ins.Add(new Instruction(RCode.Check_cast, delegateClass, new[] { next })); var nextInvokeMethod = new MethodReference(delegateClass, "Invoke", invokePrototype); var nextInvokeArgs = new[] { next }.Concat(incomingMethodArgs.Skip(1)).ToArray(); ins.Add(new Instruction(RCode.Invoke_virtual, nextInvokeMethod, nextInvokeArgs)); ins.Add(afterCallNext); // Add return instructions ins.Add(returnInstruction); return(body); }
/// <summary> /// Create the body of the equals method. /// </summary> private MethodBody CreateHashCodeBody(ClassReference delegateInstance) { MethodBody body = new MethodBody(null); // This pointer and method argument. Register rthis = body.AllocateRegister(RCategory.Argument, RType.Object); Register tempObj = body.AllocateRegister(RCategory.Temp, RType.Object); Register tempInt = body.AllocateRegister(RCategory.Temp, RType.Value); Register tempArray = body.AllocateRegister(RCategory.Temp, RType.Object); Register tempIdx = body.AllocateRegister(RCategory.Temp, RType.Value); Register tempArrayLength = body.AllocateRegister(RCategory.Temp, RType.Value); // Create code. var ins = body.Instructions; // Temporary parameter result. Register result = body.AllocateRegister(RCategory.Temp, RType.Value); var hashCodeMethod = compiler.GetDot42InternalType("Java.Lang", "System") .Resolve() .Methods.First(m => m.Name == "IdentityHashCode") .GetReference(targetPackage); // Check if other object can be casted. ins.Add(new Instruction(RCode.Const_class, delegateInstance, new[] { tempObj })); ins.Add(new Instruction(RCode.Invoke_static, hashCodeMethod, new[] { tempObj })); ins.Add(new Instruction(RCode.Move_result, null, new[] { result })); if (instanceField != null) { ins.Add(new Instruction(RCode.Mul_int_lit, 397, new[] { result, result })); ins.Add(new Instruction(RCode.Iget_object, tempObj, rthis) { Operand = instanceField }); ins.Add(new Instruction(RCode.Invoke_static, tempObj) { Operand = hashCodeMethod }); ins.Add(new Instruction(RCode.Move_result, tempInt)); ins.Add(new Instruction(RCode.Xor_int_2addr, result, tempInt)); } foreach (var field in GenericTypeFields) { if (field.Type.Equals(FrameworkReferences.Class)) { ins.Add(new Instruction(RCode.Iget_object, tempObj, rthis) { Operand = field }); ins.Add(new Instruction(RCode.Invoke_static, hashCodeMethod, new[] { tempObj })); ins.Add(new Instruction(RCode.Move_result, null, new[] { tempInt })); ins.Add(new Instruction(RCode.Xor_int_2addr, null, new[] { result, tempInt })); } else // array { ins.Add(new Instruction(RCode.Iget_object, tempArray, rthis) { Operand = field }); ins.Add(new Instruction(RCode.Array_length, tempArrayLength, rthis)); ins.Add(new Instruction(RCode.Const, tempIdx) { Operand = 0 }); Instruction loop; ins.Add(loop = new Instruction()); ins.Add(new Instruction(RCode.Mul_int_lit, 397, new[] { result, result })); ins.Add(new Instruction(RCode.Aget_object, tempObj, tempArray, tempIdx)); ins.Add(new Instruction(RCode.Invoke_static, hashCodeMethod, new[] { tempObj })); ins.Add(new Instruction(RCode.Move_result, null, new[] { tempInt })); ins.Add(new Instruction(RCode.Xor_int_2addr, null, new[] { result, tempInt })); ins.Add(new Instruction(RCode.Add_int_lit8, 1, new[] { tempIdx, tempIdx })); ins.Add(new Instruction(RCode.If_ltz, tempIdx, tempArrayLength) { Operand = loop }); } } // Add return instructions ins.Add(new Instruction(RCode.Return, null, new[] { result })); return(body); }
public void Visit(ClassReference ast) { if (!ResolvingTypes) { return; } var declaredSymbol = Resolve(ast.ClassInstance); if (declaredSymbol == null) { throw new UndefinedElementException(string.Format("Class instance '{0}' does not exist in current scope", ast.ClassInstance.Token.TokenValue)); } var classScope = Resolve(declaredSymbol.Type.TypeName) as ClassSymbol; if (classScope == null) { classScope = Global.Resolve(declaredSymbol.Type.TypeName) as ClassSymbol; } var oldScope = Current; Current = classScope; foreach (var reference in ast.Deferences) { if (reference == ast.Deferences.Last()) { reference.CallingScope = oldScope; } reference.CurrentScope = Current; reference.IsPureDynamic = Current == null; reference.Visit(this); var field = Resolve(reference); if (field == null && !reference.IsPureDynamic) { throw new InvalidSyntax(String.Format("Class {0} has no field named {1}", declaredSymbol.Type.TypeName, reference.Token.TokenValue)); } if (field != null && field.Type.ExpressionType == ExpressionTypes.UserDefined) { Current = Global.Resolve(field.Type.TypeName) as ClassSymbol; } } Current = oldScope; ast.AstSymbolType = ast.Deferences.Last().AstSymbolType; if (ast.AstSymbolType.ExpressionType == ExpressionTypes.Method) { try { ast.AstSymbolType = (ast.AstSymbolType.Src as MethodDeclr).ReturnAst.AstSymbolType; } catch (Exception ex) { } } SetScope(ast); SetScope(ast.ClassInstance); }
/// <summary> /// Create the body of the ctor. /// </summary> private static MethodBody CreateCtorBody(XMethodDefinition calledMethod, FieldDefinition instanceField, ClassReference baseClass) { var body = new MethodBody(null); // Create code var ins = body.Instructions; var rthis = body.AllocateRegister(RCategory.Argument, RType.Object); // Call base ctor var baseCtorRef = new MethodReference(baseClass, "<init>", new Prototype(PrimitiveType.Void)); ins.Add(new Instruction(RCode.Invoke_direct, rthis) { Operand = baseCtorRef }); if (!calledMethod.IsStatic) { // load instance into field var rvalue = body.AllocateRegister(RCategory.Argument, RType.Object); ins.Add(new Instruction(RCode.Iput_object, rvalue, rthis) { Operand = instanceField }); } ins.Add(new Instruction(RCode.Return_void)); return(body); }
/// <summary> /// Create an android EnclosingClass annotation and attach it to the given provider. /// </summary> public static void AddEnclosingClassAnnotation(this IAnnotationProvider provider, ClassReference @class) { var annotation = new Annotation { Type = new ClassReference("dalvik/annotation/EnclosingClass"), Visibility = AnnotationVisibility.System }; annotation.Arguments.Add(new AnnotationArgument("class", @class)); provider.Annotations.Add(annotation); }