private JsrInliner(ClassFile.Method.Instruction[] codeCopy, InstructionFlags[] flags, ClassFile.Method m, JsrMethodAnalyzer ma)
		{
			this.codeCopy = codeCopy;
			codeLength = codeCopy.Length;
			this.flags = flags;
			this.m = m;
			this.ma = ma;
		}
		private void Add(ClassFile.Method.Instruction instr)
		{
			if (codeLength == codeCopy.Length)
			{
				Array.Resize(ref codeCopy, codeLength * 2);
				Array.Resize(ref flags, codeLength * 2);
			}
			codeCopy[codeLength++] = instr;
		}
		internal static void InlineJsrs(ClassLoaderWrapper classLoader, MethodWrapper mw, ClassFile classFile, ClassFile.Method m)
		{
			JsrInliner inliner;
			do
			{
				ClassFile.Method.Instruction[] codeCopy = (ClassFile.Method.Instruction[])m.Instructions.Clone();
				InstructionFlags[] flags = new InstructionFlags[codeCopy.Length];
				JsrMethodAnalyzer ma = new JsrMethodAnalyzer(mw, classFile, m, classLoader, flags);
				inliner = new JsrInliner(codeCopy, flags, m, ma);
			} while (inliner.InlineJsrs());
		}
		internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, int constantPoolIndex, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen)
		{
			ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod);
			if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm))
			{
				return false;
			}
			LambdaMetafactory lmf = context.GetValue<LambdaMetafactory>(constantPoolIndex);
			if (lmf.ctor == null && !lmf.EmitImpl(context, classFile, cpi, bsm, ilgen))
			{
#if STATIC_COMPILER
				if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding)
				{
					StaticCompiler.IssueMessage(Message.UnableToCreateLambdaFactory);
				}
#endif
				return false;
			}
			ilgen.Emit(OpCodes.Newobj, lmf.ctor);
			// the CLR verification rules about type merging mean we have to explicitly cast to the interface type here
			ilgen.Emit(OpCodes.Castclass, cpi.GetRetType().TypeAsBaseType);
			return true;
		}
		private static int CreateCompiler(CompilerOptions options, ref CompilerClassLoader loader, ref bool compilingCoreAssembly)
		{
			Tracer.Info(Tracer.Compiler, "JVM.Compile path: {0}, assembly: {1}", options.path, options.assembly);
			AssemblyName runtimeAssemblyName = StaticCompiler.runtimeAssembly.GetName();
			bool allReferencesAreStrongNamed = IsSigned(StaticCompiler.runtimeAssembly);
			List<Assembly> references = new List<Assembly>();
			foreach(Assembly reference in options.references ?? new Assembly[0])
			{
				references.Add(reference);
				allReferencesAreStrongNamed &= IsSigned(reference);
				Tracer.Info(Tracer.Compiler, "Loaded reference assembly: {0}", reference.FullName);
				// if it's an IKVM compiled assembly, make sure that it was compiled
				// against same version of the runtime
				foreach(AssemblyName asmref in reference.GetReferencedAssemblies())
				{
					if(asmref.Name == runtimeAssemblyName.Name)
					{
						if(IsSigned(StaticCompiler.runtimeAssembly))
						{
							// TODO we really should support binding redirects here to allow different revisions to be mixed
							if(asmref.FullName != runtimeAssemblyName.FullName)
							{
								throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
							}
						}
						else
						{
							if(asmref.GetPublicKeyToken() != null && asmref.GetPublicKeyToken().Length != 0)
							{
								throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
							}
						}
					}
				}
			}
			List<object> assemblyAnnotations = new List<object>();
			Dictionary<string, string> baseClasses = new Dictionary<string, string>();
			Tracer.Info(Tracer.Compiler, "Parsing class files");
			foreach(KeyValuePair<string, ClassItem> kv in options.classes)
			{
				ClassFile f;
				try
				{
					byte[] buf = kv.Value.data;
					f = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None);
					if(!f.IsInterface && f.SuperClass != null)
					{
						baseClasses[f.SuperClass] = f.SuperClass;
					}
					// NOTE the "assembly" type in the unnamed package is a magic type
					// that acts as the placeholder for assembly attributes
					if(f.Name == "assembly" && f.Annotations != null)
					{
						assemblyAnnotations.AddRange(f.Annotations);
					}
				}
				catch(ClassFormatError)
				{
					continue;
				}
				if(options.mainClass == null && (options.guessFileKind || options.target != PEFileKinds.Dll))
				{
					foreach(ClassFile.Method m in f.Methods)
					{
						if(m.IsPublic && m.IsStatic && m.Name == "main" && m.Signature == "([Ljava.lang.String;)V")
						{
							StaticCompiler.IssueMessage(Message.MainMethodFound, f.Name);
							options.mainClass = f.Name;
							break;
						}
					}
				}
			}
			Dictionary<string, ClassItem> h = new Dictionary<string, ClassItem>();
			// HACK remove "assembly" type that exists only as a placeholder for assembly attributes
			options.classes.Remove("assembly");
			foreach(KeyValuePair<string, ClassItem> kv in options.classes)
			{
				string name = kv.Key;
				bool excluded = false;
				for(int j = 0; j < options.classesToExclude.Length; j++)
				{
					if(Regex.IsMatch(name, options.classesToExclude[j]))
					{
						excluded = true;
						break;
					}
				}
				if(h.ContainsKey(name))
				{
					StaticCompiler.IssueMessage(Message.DuplicateClassName, name);
					excluded = true;
				}
				if(!excluded)
				{
					h[name] = kv.Value;
				}
			}
			options.classes = null;

			if(options.guessFileKind && options.mainClass == null)
			{
				options.target = PEFileKinds.Dll;
			}

			if(options.target == PEFileKinds.Dll && options.mainClass != null)
			{
				throw new FatalCompilerErrorException(Message.MainClassRequiresExe);
			}

			if(options.target != PEFileKinds.Dll && options.mainClass == null)
			{
				throw new FatalCompilerErrorException(Message.ExeRequiresMainClass);
			}

			if(options.target == PEFileKinds.Dll && options.props.Count != 0)
			{
				throw new FatalCompilerErrorException(Message.PropertiesRequireExe);
			}

			if(options.path == null)
			{
				if(options.target == PEFileKinds.Dll)
				{
					if(options.targetIsModule)
					{
						options.path = options.assembly + ".netmodule";
					}
					else
					{
						options.path = options.assembly + ".dll";
					}
				}
				else
				{
					options.path = options.assembly + ".exe";
				}
				StaticCompiler.IssueMessage(Message.OutputFileIs, options.path);
			}

			if(options.targetIsModule)
			{
				if(options.classLoader != null)
				{
					throw new FatalCompilerErrorException(Message.ModuleCannotHaveClassLoader);
				}
				// TODO if we're overwriting a user specified assembly name, we need to emit a warning
				options.assembly = new FileInfo(options.path).Name;
			}

			Tracer.Info(Tracer.Compiler, "Constructing compiler");
			AssemblyClassLoader[] referencedAssemblies = new AssemblyClassLoader[references.Count];
			for(int i = 0; i < references.Count; i++)
			{
				AssemblyClassLoader acl = AssemblyClassLoader.FromAssembly(references[i]);
				if (acl.MainAssembly != references[i])
				{
					StaticCompiler.IssueMessage(options, Message.NonPrimaryAssemblyReference, references[i].GetName().Name, acl.MainAssembly.GetName().Name);
				}
				if (Array.IndexOf(referencedAssemblies, acl) != -1)
				{
					StaticCompiler.IssueMessage(options, Message.DuplicateAssemblyReference, acl.MainAssembly.FullName);
				}
				referencedAssemblies[i] = acl;
			}
			loader = new CompilerClassLoader(referencedAssemblies, options, options.path, options.targetIsModule, options.assembly, h);
			loader.baseClasses = baseClasses;
			loader.assemblyAnnotations = assemblyAnnotations;
			loader.classesToCompile = new List<string>(h.Keys);
			if(options.remapfile != null)
			{
				Tracer.Info(Tracer.Compiler, "Loading remapped types (1) from {0}", options.remapfile);
				System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(IKVM.Internal.MapXml.Root));
				ser.UnknownElement += new System.Xml.Serialization.XmlElementEventHandler(ser_UnknownElement);
				ser.UnknownAttribute += new System.Xml.Serialization.XmlAttributeEventHandler(ser_UnknownAttribute);
				FileStream fs;
				try
				{
					fs = File.OpenRead(options.remapfile);
				}
				catch(Exception x)
				{
					throw new FatalCompilerErrorException(Message.ErrorReadingFile, options.remapfile, x.Message);
				}
				try
				{
					XmlTextReader rdr = new XmlTextReader(fs);
					IKVM.Internal.MapXml.Root.xmlReader = rdr;
					IKVM.Internal.MapXml.Root map;
					try
					{
						map = (IKVM.Internal.MapXml.Root)ser.Deserialize(rdr);
					}
					catch(InvalidOperationException x)
					{
						throw new FatalCompilerErrorException(Message.ErrorParsingMapFile, options.remapfile, x.Message);
					}
					if(!loader.ValidateAndSetMap(map))
					{
						return 1;
					}
				}
				finally
				{
					fs.Close();
				}
				if(loader.CheckCompilingCoreAssembly())
				{
					compilingCoreAssembly = true;
					ClassLoaderWrapper.SetBootstrapClassLoader(loader);
				}
			}
			// If we do not yet have a reference to the core assembly and we are not compiling the core assembly,
			// try to find the core assembly by looking at the assemblies that the runtime references
			if(JVM.CoreAssembly == null && !compilingCoreAssembly)
			{
				foreach(AssemblyName name in StaticCompiler.runtimeAssembly.GetReferencedAssemblies())
				{
					Assembly asm = null;
					try
					{
						asm = LoadReferencedAssembly(StaticCompiler.runtimeAssembly.Location + "/../" + name.Name + ".dll");
					}
					catch(FileNotFoundException)
					{
					}
					if(asm != null && IsCoreAssembly(asm))
					{
						JVM.CoreAssembly = asm;
						break;
					}
				}
				if(JVM.CoreAssembly == null)
				{
					throw new FatalCompilerErrorException(Message.BootstrapClassesMissing);
				}
				// we need to scan again for remapped types, now that we've loaded the core library
				ClassLoaderWrapper.LoadRemappedTypes();
			}

			if(!compilingCoreAssembly)
			{
				allReferencesAreStrongNamed &= IsSigned(JVM.CoreAssembly);
				loader.AddReference(AssemblyClassLoader.FromAssembly(JVM.CoreAssembly));
			}

			if((options.keyPair != null || options.publicKey != null) && !allReferencesAreStrongNamed)
			{
				throw new FatalCompilerErrorException(Message.StrongNameRequiresStrongNamedRefs);
			}

			if(loader.map != null)
			{
				loader.LoadMapXml();
			}

			if(!compilingCoreAssembly)
			{
				FakeTypes.Load(JVM.CoreAssembly);
			}
			return 0;
		}
		private static object ReadAnnotationElementValue(BigEndianBinaryReader rdr, ClassFile classFile, string[] utf8_cp)
		{
			try
			{
				byte tag = rdr.ReadByte();
				switch (tag)
				{
					case (byte)'Z':
						return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()) != 0;
					case (byte)'B':
						return (byte)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16());
					case (byte)'C':
						return (char)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16());
					case (byte)'S':
						return (short)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16());
					case (byte)'I':
						return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16());
					case (byte)'F':
						return classFile.GetConstantPoolConstantFloat(rdr.ReadUInt16());
					case (byte)'J':
						return classFile.GetConstantPoolConstantLong(rdr.ReadUInt16());
					case (byte)'D':
						return classFile.GetConstantPoolConstantDouble(rdr.ReadUInt16());
					case (byte)'s':
						return classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16());
					case (byte)'e':
						{
							ushort type_name_index = rdr.ReadUInt16();
							ushort const_name_index = rdr.ReadUInt16();
							return new object[] {
											AnnotationDefaultAttribute.TAG_ENUM,
											classFile.GetConstantPoolUtf8String(utf8_cp, type_name_index),
											classFile.GetConstantPoolUtf8String(utf8_cp, const_name_index)
										};
						}
					case (byte)'c':
						return new object[] {
											AnnotationDefaultAttribute.TAG_CLASS,
											classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16())
										};
					case (byte)'@':
						return ReadAnnotation(rdr, classFile, utf8_cp);
					case (byte)'[':
						{
							ushort num_values = rdr.ReadUInt16();
							object[] array = new object[num_values + 1];
							array[0] = AnnotationDefaultAttribute.TAG_ARRAY;
							for (int i = 0; i < num_values; i++)
							{
								array[i + 1] = ReadAnnotationElementValue(rdr, classFile, utf8_cp);
							}
							return array;
						}
					default:
						throw new ClassFormatError("Invalid tag {0} in annotation element_value", tag);
				}
			}
			catch (NullReferenceException)
			{
			}
			catch (InvalidCastException)
			{
			}
			catch (IndexOutOfRangeException)
			{
			}
			return new object[] { AnnotationDefaultAttribute.TAG_ERROR, "java.lang.IllegalArgumentException", "Wrong type at constant pool index" };
		}
		private static object[] ReadAnnotations(BigEndianBinaryReader br, ClassFile classFile, string[] utf8_cp)
		{
			BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
			ushort num_annotations = rdr.ReadUInt16();
			object[] annotations = new object[num_annotations];
			for(int i = 0; i < annotations.Length; i++)
			{
				annotations[i] = ReadAnnotation(rdr, classFile, utf8_cp);
			}
			if(!rdr.IsAtEnd)
			{
				throw new ClassFormatError("{0} (RuntimeVisibleAnnotations attribute has wrong length)", classFile.Name);
			}
			return annotations;
		}
示例#8
0
 protected override bool IsPInvokeMethod(ClassFile.Method m)
 {
     Dictionary<string, IKVM.Internal.MapXml.Class> mapxml = classLoader.GetMapXmlClasses();
     if(mapxml != null)
     {
         IKVM.Internal.MapXml.Class clazz;
         if(mapxml.TryGetValue(this.Name, out clazz) && clazz.Methods != null)
         {
             foreach(IKVM.Internal.MapXml.Method method in clazz.Methods)
             {
                 if(method.Name == m.Name && method.Sig == m.Signature)
                 {
                     if(method.Attributes != null)
                     {
                         foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes)
                         {
                             if(StaticCompiler.GetType(classLoader, attr.Type) == JVM.Import(typeof(System.Runtime.InteropServices.DllImportAttribute)))
                             {
                                 return true;
                             }
                         }
                     }
                     break;
                 }
             }
         }
     }
     return base.IsPInvokeMethod(m);
 }
示例#9
0
 protected override bool EmitMapXmlMethodPrologueAndOrBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m)
 {
     IKVM.Internal.MapXml.InstructionList prologue = classLoader.GetMethodPrologue(new MethodKey(f.Name, m.Name, m.Signature));
     if(prologue != null)
     {
         prologue.Emit(classLoader, ilgen);
     }
     Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList> mapxml = classLoader.GetMapXmlMethodBodies();
     if(mapxml != null)
     {
         IKVM.Internal.MapXml.InstructionList opcodes;
         if(mapxml.TryGetValue(new MethodKey(f.Name, m.Name, m.Signature), out opcodes))
         {
             opcodes.Emit(classLoader, ilgen);
             return true;
         }
     }
     return false;
 }
示例#10
0
 internal ReplacedMethodWrapper(ClassFile.ConstantPoolItemMI cpi, IKVM.Internal.MapXml.InstructionList code)
     : base(cpi.GetClassType(), cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), Modifiers.Public, MemberFlags.None)
 {
     this.code = code;
 }
		private static bool IsSupportedImplMethod(ClassFile.ConstantPoolItemMethodHandle implMethod, TypeWrapper caller, TypeWrapper[] captured, ClassFile.ConstantPoolItemMethodType instantiatedMethodType)
		{
			switch (implMethod.Kind)
			{
				case ClassFile.RefKind.invokeVirtual:
				case ClassFile.RefKind.invokeInterface:
				case ClassFile.RefKind.newInvokeSpecial:
				case ClassFile.RefKind.invokeStatic:
				case ClassFile.RefKind.invokeSpecial:
					break;
				default:
					return false;
			}
			MethodWrapper mw = (MethodWrapper)implMethod.Member;
			if (mw == null || mw.HasCallerID || DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(mw.DeclaringType.Name, mw.Name, mw.Signature))
			{
				return false;
			}
			TypeWrapper instance;
			if (mw.IsConstructor)
			{
				instance = mw.DeclaringType;
			}
			else if (mw.IsStatic)
			{
				instance = null;
			}
			else
			{
				// if implMethod is an instance method, the type of the first captured value must be subtype of implMethod.DeclaringType
				instance = captured.Length == 0 ? instantiatedMethodType.GetArgTypes()[0] : captured[0];
				if (!instance.IsAssignableTo(mw.DeclaringType))
				{
					return false;
				}
			}
			if (!mw.IsAccessibleFrom(mw.DeclaringType, caller, instance))
			{
				return false;
			}
			mw.Link();
			return true;
		}
		private bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen)
		{
			if (HasUnloadable(cpi))
			{
				Fail("cpi has unloadable");
				return false;
			}
			bool serializable = false;
			TypeWrapper[] markers = TypeWrapper.EmptyArray;
			ClassFile.ConstantPoolItemMethodType[] bridges = null;
			if (bsm.ArgumentCount > 3)
			{
				AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3));
				serializable = (flags & AltFlags.Serializable) != 0;
				int argpos = 4;
				if ((flags & AltFlags.Markers) != 0)
				{
					markers = new TypeWrapper[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))];
					for (int i = 0; i < markers.Length; i++)
					{
						if ((markers[i] = classFile.GetConstantPoolClassType(bsm.GetArgument(argpos++))).IsUnloadable)
						{
							Fail("unloadable marker");
							return false;
						}
					}
				}
				if ((flags & AltFlags.Bridges) != 0)
				{
					bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))];
					for (int i = 0; i < bridges.Length; i++)
					{
						bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++));
						if (HasUnloadable(bridges[i]))
						{
							Fail("unloadable bridge");
							return false;
						}
					}
				}
			}
			ClassFile.ConstantPoolItemMethodType samMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0));
			ClassFile.ConstantPoolItemMethodHandle implMethod = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1));
			ClassFile.ConstantPoolItemMethodType instantiatedMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(2));
			if (HasUnloadable(samMethodType)
				|| HasUnloadable((ClassFile.ConstantPoolItemMI)implMethod.MemberConstantPoolItem)
				|| HasUnloadable(instantiatedMethodType))
			{
				Fail("bsm args has unloadable");
				return false;
			}
			TypeWrapper interfaceType = cpi.GetRetType();
			MethodWrapper[] methodList;
			if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList))
			{
				Fail("unsupported interface");
				return false;
			}
			if (serializable && Array.Exists(methodList, delegate(MethodWrapper mw) { return mw.Name == "writeReplace" && mw.Signature == "()Ljava.lang.Object;"; }))
			{
				Fail("writeReplace");
				return false;
			}
			if (!IsSupportedImplMethod(implMethod, context.TypeWrapper, cpi.GetArgTypes(), instantiatedMethodType))
			{
				Fail("implMethod " + implMethod.MemberConstantPoolItem.Class + "::" + implMethod.MemberConstantPoolItem.Name + implMethod.MemberConstantPoolItem.Signature);
				return false;
			}
			TypeWrapper[] implParameters = GetImplParameters(implMethod);
			CheckConstraints(instantiatedMethodType, samMethodType, cpi.GetArgTypes(), implParameters);
			if (bridges != null)
			{
				foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges)
				{
					if (bridge.Signature == samMethodType.Signature)
					{
						Fail("bridge signature matches sam");
						return false;
					}
					if (!CheckConstraints(instantiatedMethodType, bridge, cpi.GetArgTypes(), implParameters))
					{
						Fail("bridge constraints");
						return false;
					}
				}
			}
			if (instantiatedMethodType.GetRetType() != PrimitiveTypeWrapper.VOID)
			{
				TypeWrapper Rt = instantiatedMethodType.GetRetType();
				TypeWrapper Ra = GetImplReturnType(implMethod);
				if (Ra == PrimitiveTypeWrapper.VOID || !IsAdaptable(Ra, Rt, true))
				{
					Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt");
					return false;
				}
			}
			MethodWrapper interfaceMethod = null;
			List<MethodWrapper> methods = new List<MethodWrapper>();
			foreach (MethodWrapper mw in methodList)
			{
				if (mw.Name == cpi.Name && mw.Signature == samMethodType.Signature)
				{
					interfaceMethod = mw;
					methods.Add(mw);
				}
				else if (mw.IsAbstract && !IsObjectMethod(mw))
				{
					methods.Add(mw);
				}
			}
			if (interfaceMethod == null || !interfaceMethod.IsAbstract || IsObjectMethod(interfaceMethod) || !MatchSignatures(interfaceMethod, samMethodType))
			{
				Fail("interfaceMethod");
				return false;
			}

			TypeBuilder tb = context.DefineAnonymousClass();
			// we're not implementing the interfaces recursively (because we don't care about .NET Compact anymore),
			// but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is
			tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType);
			if (serializable && Array.IndexOf(markers, CoreClasses.java.io.Serializable.Wrapper) == -1)
			{
				tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType);
			}
			foreach (TypeWrapper marker in markers)
			{
				tb.AddInterfaceImplementation(marker.TypeAsBaseType);
			}
			ctor = CreateConstructorAndDispatch(context, cpi, tb, methods, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable);
			AddDefaultInterfaceMethods(context, methodList, tb);
			return true;
		}
		private static void EmitDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters,
			ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, FieldBuilder[] capturedFields)
		{
			MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final);
			if (interfaceMethod.Name != interfaceMethod.RealName)
			{
				tb.DefineMethodOverride(mb, (MethodInfo)interfaceMethod.GetMethod());
			}
			CodeEmitter ilgen = CodeEmitter.Create(mb);
			for (int i = 0; i < capturedFields.Length; i++)
			{
				ilgen.EmitLdarg(0);
				OpCode opc = OpCodes.Ldfld;
				if (i == 0 && args[0].IsGhost)
				{
					switch (implMethod.Kind)
					{
						case ClassFile.RefKind.invokeInterface:
						case ClassFile.RefKind.invokeVirtual:
						case ClassFile.RefKind.invokeSpecial:
							opc = OpCodes.Ldflda;
							break;
					}
				}
				ilgen.Emit(opc, capturedFields[i]);
			}
			for (int i = 0, count = interfaceMethod.GetParameters().Length, k = capturedFields.Length; i < count; i++)
			{
				ilgen.EmitLdarg(i + 1);
				TypeWrapper Ui = interfaceMethod.GetParameters()[i];
				TypeWrapper Ti = instantiatedMethodType.GetArgTypes()[i];
				TypeWrapper Aj = implParameters[i + k];
				if (Ui == PrimitiveTypeWrapper.BYTE)
				{
					ilgen.Emit(OpCodes.Conv_I1);
				}
				if (Ti != Ui)
				{
					if (Ti.IsGhost)
					{
						Ti.EmitConvStackTypeToSignatureType(ilgen, Ui);
					}
					else if (Ui.IsGhost)
					{
						Ui.EmitConvSignatureTypeToStackType(ilgen);
					}
					else
					{
						Ti.EmitCheckcast(ilgen);
					}
				}
				if (Ti != Aj)
				{
					if (Ti.IsPrimitive && !Aj.IsPrimitive)
					{
						Boxer.EmitBox(ilgen, Ti);
					}
					else if (!Ti.IsPrimitive && Aj.IsPrimitive)
					{
						TypeWrapper primitive = GetPrimitiveFromWrapper(Ti);
						Boxer.EmitUnbox(ilgen, primitive, false);
						if (primitive == PrimitiveTypeWrapper.BYTE)
						{
							ilgen.Emit(OpCodes.Conv_I1);
						}
					}
					else if (Aj == PrimitiveTypeWrapper.LONG)
					{
						ilgen.Emit(OpCodes.Conv_I8);
					}
					else if (Aj == PrimitiveTypeWrapper.FLOAT)
					{
						ilgen.Emit(OpCodes.Conv_R4);
					}
					else if (Aj == PrimitiveTypeWrapper.DOUBLE)
					{
						ilgen.Emit(OpCodes.Conv_R8);
					}
				}
			}
			switch (implMethod.Kind)
			{
				case ClassFile.RefKind.invokeVirtual:
				case ClassFile.RefKind.invokeInterface:
					((MethodWrapper)implMethod.Member).EmitCallvirt(ilgen);
					break;
				case ClassFile.RefKind.newInvokeSpecial:
					((MethodWrapper)implMethod.Member).EmitNewobj(ilgen);
					break;
				case ClassFile.RefKind.invokeStatic:
				case ClassFile.RefKind.invokeSpecial:
					((MethodWrapper)implMethod.Member).EmitCall(ilgen);
					break;
				default:
					throw new InvalidOperationException();
			}
			TypeWrapper Ru = interfaceMethod.ReturnType;
			TypeWrapper Ra = GetImplReturnType(implMethod);
			TypeWrapper Rt = instantiatedMethodType.GetRetType();
			if (Ra == PrimitiveTypeWrapper.BYTE)
			{
				ilgen.Emit(OpCodes.Conv_I1);
			}
			if (Ra != Ru)
			{
				if (Ru == PrimitiveTypeWrapper.VOID)
				{
					ilgen.Emit(OpCodes.Pop);
				}
				else if (Ra.IsGhost)
				{
					Ra.EmitConvSignatureTypeToStackType(ilgen);
				}
				else if (Ru.IsGhost)
				{
					Ru.EmitConvStackTypeToSignatureType(ilgen, Ra);
				}
			}
			if (Ra != Rt)
			{
				if (Rt.IsPrimitive)
				{
					if (Rt == PrimitiveTypeWrapper.VOID)
					{
						// already popped
					}
					else if (!Ra.IsPrimitive)
					{
						TypeWrapper primitive = GetPrimitiveFromWrapper(Ra);
						if (primitive != null)
						{
							Boxer.EmitUnbox(ilgen, primitive, false);
						}
						else
						{
							// If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types
							EmitConvertingUnbox(ilgen, Rt);
						}
					}
					else if (Rt == PrimitiveTypeWrapper.LONG)
					{
						ilgen.Emit(OpCodes.Conv_I8);
					}
					else if (Rt == PrimitiveTypeWrapper.FLOAT)
					{
						ilgen.Emit(OpCodes.Conv_R4);
					}
					else if (Rt == PrimitiveTypeWrapper.DOUBLE)
					{
						ilgen.Emit(OpCodes.Conv_R8);
					}
				}
				else if (Ra.IsPrimitive)
				{
					Boxer.EmitBox(ilgen, GetPrimitiveFromWrapper(Rt));
				}
				else
				{
					Rt.EmitCheckcast(ilgen);
				}
			}
			ilgen.EmitTailCallPrevention();
			ilgen.Emit(OpCodes.Ret);
			ilgen.DoEmit();
		}
		private static MethodBuilder CreateConstructorAndDispatch(DynamicTypeWrapper.FinishContext context, ClassFile.ConstantPoolItemInvokeDynamic cpi, TypeBuilder tb,
			List<MethodWrapper> methods, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod,
			ClassFile.ConstantPoolItemMethodType instantiatedMethodType, bool serializable)
		{
			TypeWrapper[] args = cpi.GetArgTypes();

			// captured values
			Type[] capturedTypes = new Type[args.Length];
			FieldBuilder[] capturedFields = new FieldBuilder[capturedTypes.Length];
			for (int i = 0; i < capturedTypes.Length; i++)
			{
				capturedTypes[i] = args[i].TypeAsSignatureType;
				FieldAttributes attr = FieldAttributes.Private;
				if (i > 0 || !args[0].IsGhost)
				{
					attr |= FieldAttributes.InitOnly;
				}
				capturedFields[i] = tb.DefineField("arg$" + (i + 1), capturedTypes[i], attr);
			}

			// constructor
			MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, capturedTypes);
			CodeEmitter ilgen = CodeEmitter.Create(ctor);
			ilgen.Emit(OpCodes.Ldarg_0);
			ilgen.Emit(OpCodes.Call, Types.Object.GetConstructor(Type.EmptyTypes));
			for (int i = 0; i < capturedTypes.Length; i++)
			{
				ilgen.EmitLdarg(0);
				ilgen.EmitLdarg(i + 1);
				ilgen.Emit(OpCodes.Stfld, capturedFields[i]);
			}
			ilgen.Emit(OpCodes.Ret);
			ilgen.DoEmit();

			// dispatch methods
			foreach (MethodWrapper mw in methods)
			{
				EmitDispatch(context, args, tb, mw, implParameters, implMethod, instantiatedMethodType, capturedFields);
			}

			// writeReplace method
			if (serializable)
			{
				MethodBuilder writeReplace = tb.DefineMethod("writeReplace", MethodAttributes.Private, Types.Object, Type.EmptyTypes);
				ilgen = CodeEmitter.Create(writeReplace);
				context.TypeWrapper.EmitClassLiteral(ilgen);
				ilgen.Emit(OpCodes.Ldstr, cpi.GetRetType().Name.Replace('.', '/'));
				ilgen.Emit(OpCodes.Ldstr, cpi.Name);
				ilgen.Emit(OpCodes.Ldstr, samMethodType.Signature.Replace('.', '/'));
				ilgen.EmitLdc_I4((int)implMethod.Kind);
				ilgen.Emit(OpCodes.Ldstr, implMethod.Class.Replace('.', '/'));
				ilgen.Emit(OpCodes.Ldstr, implMethod.Name);
				ilgen.Emit(OpCodes.Ldstr, implMethod.Signature.Replace('.', '/'));
				ilgen.Emit(OpCodes.Ldstr, instantiatedMethodType.Signature.Replace('.', '/'));
				ilgen.EmitLdc_I4(capturedFields.Length);
				ilgen.Emit(OpCodes.Newarr, Types.Object);
				for (int i = 0; i < capturedFields.Length; i++)
				{
					ilgen.Emit(OpCodes.Dup);
					ilgen.EmitLdc_I4(i);
					ilgen.EmitLdarg(0);
					ilgen.Emit(OpCodes.Ldfld, capturedFields[i]);
					if (args[i].IsPrimitive)
					{
						Boxer.EmitBox(ilgen, args[i]);
					}
					else if (args[i].IsGhost)
					{
						args[i].EmitConvSignatureTypeToStackType(ilgen);
					}
					ilgen.Emit(OpCodes.Stelem, Types.Object);
				}
				MethodWrapper ctorSerializedLambda = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.SerializedLambda").GetMethodWrapper(StringConstants.INIT,
					"(Ljava.lang.Class;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;ILjava.lang.String;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;[Ljava.lang.Object;)V", false);
				ctorSerializedLambda.Link();
				ctorSerializedLambda.EmitNewobj(ilgen);
				ilgen.Emit(OpCodes.Ret);
				ilgen.DoEmit();

				if (!context.TypeWrapper.GetClassLoader().NoAutomagicSerialization)
				{
					// add .NET serialization interop support
					Serialization.MarkSerializable(tb);
					Serialization.AddGetObjectData(tb);
				}
			}

			return ctor;
		}
		private static bool IsSubTypeOf(ClassFile.ConstantPoolItemMethodType instantiatedMethodType, ClassFile.ConstantPoolItemMethodType samMethodType)
		{
			TypeWrapper[] T = instantiatedMethodType.GetArgTypes();
			TypeWrapper[] U = samMethodType.GetArgTypes();
			if (T.Length != U.Length)
			{
				return false;
			}
			for (int i = 0; i < T.Length; i++)
			{
				if (!T[i].IsAssignableTo(U[i]))
				{
					return false;
				}
			}
			TypeWrapper Rt = instantiatedMethodType.GetRetType();
			TypeWrapper Ru = samMethodType.GetRetType();
			return Rt.IsAssignableTo(Ru);
		}
示例#16
0
		private TypeWrapper GetTypeWrapperCompilerHook(string name)
		{
			RemapperTypeWrapper rtw;
			if(remapped.TryGetValue(name, out rtw))
			{
				return rtw;
			}
			else
			{
				Jar.Item itemRef;
				if(classes.TryGetValue(name, out itemRef))
				{
					classes.Remove(name);
					ClassFile f;
					try
					{
						byte[] buf = itemRef.GetData();
						f = new ClassFile(buf, 0, buf.Length, name, ClassFileParseOptions, null);
					}
					catch(ClassFormatError x)
					{
						StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name);
						StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
						return null;
					}
					if(f.Name != name)
					{
						StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name);
						StaticCompiler.IssueMessage(options, Message.WrongClassName, name, f.Name);
						return null;
					}
					if(options.removeUnusedFields)
					{
						f.RemoveUnusedFields();
					}
					if(f.IsPublic && options.privatePackages != null)
					{
						foreach(string p in options.privatePackages)
						{
							if(f.Name.StartsWith(p))
							{
								f.SetInternal();
								break;
							}
						}
					}
					if(f.IsPublic && options.publicPackages != null)
					{
						bool found = false;
						foreach(string package in options.publicPackages)
						{
							if(f.Name.StartsWith(package))
							{
								found = true;
								break;
							}
						}
						if(!found)
						{
							f.SetInternal();
						}
					}
					if(f.SourceFileAttribute != null)
					{
						FileInfo path = itemRef.Path;
						if(path != null)
						{
							string sourceFile = Path.GetFullPath(Path.Combine(path.DirectoryName, f.SourceFileAttribute));
							if(File.Exists(sourceFile))
							{
								f.SourcePath = sourceFile;
							}
						}
						if(f.SourcePath == null)
						{
							if (options.sourcepath != null)
							{
								string package = f.Name;
								int index = package.LastIndexOf('.');
								package = index == -1 ? "" : package.Substring(0, index).Replace('.', '/');
								f.SourcePath = Path.GetFullPath(Path.Combine(options.sourcepath + "/" + package, f.SourceFileAttribute));
							}
							else
							{
								f.SourcePath = f.SourceFileAttribute;
							}
						}
					}
					try
					{
						TypeWrapper tw = DefineClass(f, null);
						// we successfully created the type, so we don't need to include the class as a resource
						if (options.nojarstubs)
						{
							itemRef.Remove();
						}
						else
						{
							itemRef.MarkAsStub();
						}
						int pos = f.Name.LastIndexOf('.');
						if (pos != -1)
						{
							string manifestJar = options.IsClassesJar(itemRef.Jar) ? null : itemRef.Jar.Name;
							packages.DefinePackage(f.Name.Substring(0, pos), manifestJar);
						}
						return tw;
					}
					catch (ClassFormatError x)
					{
						StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
					}
					catch (IllegalAccessError x)
					{
						StaticCompiler.IssueMessage(options, Message.IllegalAccessError, name, x.Message);
					}
					catch (VerifyError x)
					{
						StaticCompiler.IssueMessage(options, Message.VerificationError, name, x.Message);
					}
					catch (NoClassDefFoundError x)
					{
						if ((options.codegenoptions & CodeGenOptions.DisableDynamicBinding) != 0)
						{
							StaticCompiler.IssueMessage(options, Message.NoClassDefFoundError, name, x.Message);
						}
						StaticCompiler.IssueMessage(options, Message.ClassNotFound, x.Message);
					}
					catch (RetargetableJavaException x)
					{
						StaticCompiler.IssueMessage(options, Message.GenericUnableToCompileError, name, x.GetType().Name, x.Message);
					}
					StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name);
					return null;
				}
				else
				{
					return null;
				}
			}
		}
示例#17
0
		private static int CreateCompiler(CompilerOptions options, ref CompilerClassLoader loader, ref bool compilingCoreAssembly)
		{
			Tracer.Info(Tracer.Compiler, "JVM.Compile path: {0}, assembly: {1}", options.path, options.assembly);
			AssemblyName runtimeAssemblyName = StaticCompiler.runtimeAssembly.GetName();
			bool allReferencesAreStrongNamed = IsSigned(StaticCompiler.runtimeAssembly);
			List<Assembly> references = new List<Assembly>();
			foreach(Assembly reference in options.references ?? new Assembly[0])
			{
				references.Add(reference);
				allReferencesAreStrongNamed &= IsSigned(reference);
				Tracer.Info(Tracer.Compiler, "Loaded reference assembly: {0}", reference.FullName);
				// if it's an IKVM compiled assembly, make sure that it was compiled
				// against same version of the runtime
				foreach(AssemblyName asmref in reference.GetReferencedAssemblies())
				{
					if(asmref.Name == runtimeAssemblyName.Name)
					{
						if(IsSigned(StaticCompiler.runtimeAssembly))
						{
							// TODO we really should support binding redirects here to allow different revisions to be mixed
							if(asmref.FullName != runtimeAssemblyName.FullName)
							{
								throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
							}
						}
						else
						{
							if(asmref.GetPublicKeyToken() != null && asmref.GetPublicKeyToken().Length != 0)
							{
								throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName);
							}
						}
					}
				}
			}
			Tracer.Info(Tracer.Compiler, "Parsing class files");
			// map the class names to jar entries
			Dictionary<string, Jar.Item> h = new Dictionary<string, Jar.Item>();
			List<string> classNames = new List<string>();
			foreach (Jar jar in options.jars)
			{
				if (options.IsResourcesJar(jar))
				{
					continue;
				}
				foreach (Jar.Item item in jar)
				{
					string name = item.Name;
					if (name.EndsWith(".class", StringComparison.Ordinal)
						&& name.Length > 6
						&& name.IndexOf('.') == name.Length - 6)
					{
						string className = name.Substring(0, name.Length - 6).Replace('/', '.');
						if (h.ContainsKey(className))
						{
							StaticCompiler.IssueMessage(Message.DuplicateClassName, className);
							Jar.Item itemRef = h[className];
							if ((options.classesJar != -1 && itemRef.Jar == options.jars[options.classesJar]) || jar != itemRef.Jar)
							{
								// the previous class stays, because it was either in an earlier jar or we're processing the classes.jar
								// which contains the classes loaded from the file system (where the first encountered class wins)
								continue;
							}
							else
							{
								// we have a jar that contains multiple entries with the same name, the last one wins
								h.Remove(className);
								classNames.Remove(className);
							}
						}
						h.Add(className, item);
						classNames.Add(className);
					}
				}
			}

			if (options.assemblyAttributeAnnotations == null)
			{
				// look for "assembly" type that acts as a placeholder for assembly attributes
				Jar.Item assemblyType;
				if (h.TryGetValue("assembly", out assemblyType))
				{
					try
					{
						byte[] buf = assemblyType.GetData();
						ClassFile f = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None, null);
						// NOTE the "assembly" type in the unnamed package is a magic type
						// that acts as the placeholder for assembly attributes
						if (f.Name == "assembly" && f.Annotations != null)
						{
							options.assemblyAttributeAnnotations = f.Annotations;
							// HACK remove "assembly" type that exists only as a placeholder for assembly attributes
							h.Remove(f.Name);
							assemblyType.Remove();
							StaticCompiler.IssueMessage(Message.LegacyAssemblyAttributesFound);
						}
					}
					catch (ClassFormatError) { }
				}
			}

			// now look for a main method
			if (options.mainClass == null && (options.guessFileKind || options.target != PEFileKinds.Dll))
			{
				foreach (string className in classNames)
				{
					try
					{
						byte[] buf = h[className].GetData();
						ClassFile f = new ClassFile(buf, 0, buf.Length, null, ClassFileParseOptions.None, null);
						if (f.Name == className)
						{
							foreach (ClassFile.Method m in f.Methods)
							{
								if (m.IsPublic && m.IsStatic && m.Name == "main" && m.Signature == "([Ljava.lang.String;)V")
								{
									StaticCompiler.IssueMessage(Message.MainMethodFound, f.Name);
									options.mainClass = f.Name;
									goto break_outer;
								}
							}
						}
					}
					catch (ClassFormatError) { }
				}
			break_outer: ;
			}

			if(options.guessFileKind && options.mainClass == null)
			{
				options.target = PEFileKinds.Dll;
			}

			if(options.target == PEFileKinds.Dll && options.mainClass != null)
			{
				throw new FatalCompilerErrorException(Message.MainClassRequiresExe);
			}

			if(options.target != PEFileKinds.Dll && options.mainClass == null)
			{
				throw new FatalCompilerErrorException(Message.ExeRequiresMainClass);
			}

			if(options.target == PEFileKinds.Dll && options.props.Count != 0)
			{
				throw new FatalCompilerErrorException(Message.PropertiesRequireExe);
			}

			if(options.path == null)
			{
				if(options.target == PEFileKinds.Dll)
				{
					if(options.targetIsModule)
					{
						options.path = IkvmcCompiler.GetFileInfo(options.assembly + ".netmodule");
					}
					else
					{
						options.path = IkvmcCompiler.GetFileInfo(options.assembly + ".dll");
					}
				}
				else
				{
					options.path = IkvmcCompiler.GetFileInfo(options.assembly + ".exe");
				}
				StaticCompiler.IssueMessage(Message.OutputFileIs, options.path.ToString());
			}

			if(options.targetIsModule)
			{
				if(options.classLoader != null)
				{
					throw new FatalCompilerErrorException(Message.ModuleCannotHaveClassLoader);
				}
				// TODO if we're overwriting a user specified assembly name, we need to emit a warning
				options.assembly = options.path.Name;
			}

			Tracer.Info(Tracer.Compiler, "Constructing compiler");
			AssemblyClassLoader[] referencedAssemblies = new AssemblyClassLoader[references.Count];
			for(int i = 0; i < references.Count; i++)
			{
				AssemblyClassLoader acl = AssemblyClassLoader.FromAssembly(references[i]);
				if (Array.IndexOf(referencedAssemblies, acl) != -1)
				{
					StaticCompiler.IssueMessage(options, Message.DuplicateAssemblyReference, acl.MainAssembly.FullName);
				}
				referencedAssemblies[i] = acl;
			}
			loader = new CompilerClassLoader(referencedAssemblies, options, options.path, options.targetIsModule, options.assembly, h, compilingCoreAssembly);
			loader.classesToCompile = new List<string>(h.Keys);
			if(options.remapfile != null)
			{
				Tracer.Info(Tracer.Compiler, "Loading remapped types (1) from {0}", options.remapfile);
				System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(IKVM.Internal.MapXml.Root));
				ser.UnknownElement += new System.Xml.Serialization.XmlElementEventHandler(ser_UnknownElement);
				ser.UnknownAttribute += new System.Xml.Serialization.XmlAttributeEventHandler(ser_UnknownAttribute);
				FileStream fs;
				try
				{
					fs = options.remapfile.OpenRead();
				}
				catch(Exception x)
				{
					throw new FatalCompilerErrorException(Message.ErrorReadingFile, options.remapfile, x.Message);
				}
				try
				{
					XmlTextReader rdr = new XmlTextReader(fs);
					IKVM.Internal.MapXml.Root.xmlReader = rdr;
					IKVM.Internal.MapXml.Root map;
					try
					{
						map = (IKVM.Internal.MapXml.Root)ser.Deserialize(rdr);
					}
					catch(InvalidOperationException x)
					{
						throw new FatalCompilerErrorException(Message.ErrorParsingMapFile, options.remapfile, x.Message);
					}
					if(!loader.ValidateAndSetMap(map))
					{
						return 1;
					}
				}
				finally
				{
					fs.Close();
				}
				if(loader.CheckCompilingCoreAssembly())
				{
					compilingCoreAssembly = true;
					ClassLoaderWrapper.SetBootstrapClassLoader(loader);
				}
			}
			// If we do not yet have a reference to the core assembly and we are not compiling the core assembly,
			// try to find the core assembly by looking at the assemblies that the runtime references
			if(JVM.CoreAssembly == null && !compilingCoreAssembly)
			{
				foreach(AssemblyName name in StaticCompiler.runtimeAssembly.GetReferencedAssemblies())
				{
					Assembly asm = null;
					try
					{
						asm = LoadReferencedAssembly(StaticCompiler.runtimeAssembly.Location + "/../" + name.Name + ".dll");
					}
					catch(FileNotFoundException)
					{
					}
					if(asm != null && IsCoreAssembly(asm))
					{
						AssemblyClassLoader.PreloadExportedAssemblies(asm);
						JVM.CoreAssembly = asm;
						break;
					}
				}
				if(JVM.CoreAssembly == null)
				{
					throw new FatalCompilerErrorException(Message.BootstrapClassesMissing);
				}
				// we need to scan again for remapped types, now that we've loaded the core library
				ClassLoaderWrapper.LoadRemappedTypes();
			}

			if(!compilingCoreAssembly)
			{
				allReferencesAreStrongNamed &= IsSigned(JVM.CoreAssembly);
				loader.AddReference(AssemblyClassLoader.FromAssembly(JVM.CoreAssembly));
			}

			if((options.keyPair != null || options.publicKey != null) && !allReferencesAreStrongNamed)
			{
				throw new FatalCompilerErrorException(Message.StrongNameRequiresStrongNamedRefs);
			}

			if(loader.map != null)
			{
				loader.LoadMapXml();
			}

			if(!compilingCoreAssembly)
			{
				FakeTypes.Load(JVM.CoreAssembly);
			}
			return 0;
		}
		private static bool CheckSupportedInterfaces(TypeWrapper caller, TypeWrapper tw, TypeWrapper[] markers, ClassFile.ConstantPoolItemMethodType[] bridges, out MethodWrapper[] methodList)
		{
			// we don't need to check for unloadable, because we already did that while validating the invoke signature
			if (!IsSupportedInterface(tw, caller))
			{
				methodList = null;
				return false;
			}
			Dictionary<MethodKey, MethodWrapper> methods = new Dictionary<MethodKey,MethodWrapper>();
			int abstractMethodCount = 0;
			int bridgeMethodCount = 0;
			if (GatherAllInterfaceMethods(tw, bridges, methods, ref abstractMethodCount, ref bridgeMethodCount) && abstractMethodCount == 1)
			{
				foreach (TypeWrapper marker in markers)
				{
					if (!IsSupportedInterface(marker, caller))
					{
						methodList = null;
						return false;
					}
					if (!GatherAllInterfaceMethods(marker, null, methods, ref abstractMethodCount, ref bridgeMethodCount) || abstractMethodCount != 1)
					{
						methodList = null;
						return false;
					}
				}
				if (bridges != null && bridgeMethodCount != bridges.Length)
				{
					methodList = null;
					return false;
				}
				methodList = new MethodWrapper[methods.Count];
				methods.Values.CopyTo(methodList, 0);
				return true;
			}
			methodList = null;
			return false;
		}
示例#19
0
 protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods)
 {
     Dictionary<string, IKVM.Internal.MapXml.Class> mapxml = classLoader.GetMapXmlClasses();
     if(mapxml != null)
     {
         IKVM.Internal.MapXml.Class clazz;
         if(mapxml.TryGetValue(classFile.Name, out clazz))
         {
             if(clazz.Attributes != null)
             {
                 PublishAttributes(typeBuilder, clazz);
             }
             if(clazz.Properties != null)
             {
                 PublishProperties(typeBuilder, clazz);
             }
             if(clazz.Fields != null)
             {
                 foreach(IKVM.Internal.MapXml.Field field in clazz.Fields)
                 {
                     if(field.Attributes != null)
                     {
                         foreach(FieldWrapper fw in fields)
                         {
                             if(fw.Name == field.Name && fw.Signature == field.Sig)
                             {
                                 FieldBuilder fb = fw.GetField() as FieldBuilder;
                                 if(fb != null)
                                 {
                                     foreach(IKVM.Internal.MapXml.Attribute attr in field.Attributes)
                                     {
                                         AttributeHelper.SetCustomAttribute(classLoader, fb, attr);
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             if(clazz.Constructors != null)
             {
                 // HACK this isn't the right place to do this, but for now it suffices
                 foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors)
                 {
                     // are we adding a new constructor?
                     if(GetMethodWrapper(StringConstants.INIT, constructor.Sig, false) == null)
                     {
                         if(constructor.body == null)
                         {
                             Console.Error.WriteLine("Error: Constructor {0}.<init>{1} in xml remap file doesn't have a body.", clazz.Name, constructor.Sig);
                             continue;
                         }
                         bool setmodifiers = false;
                         MethodAttributes attribs = 0;
                         MapModifiers(constructor.Modifiers, true, out setmodifiers, ref attribs);
                         Type returnType;
                         Type[] parameterTypes;
                         MapSignature(constructor.Sig, out returnType, out parameterTypes);
                         MethodBuilder cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes);
                         if(setmodifiers)
                         {
                             AttributeHelper.SetModifiers(cb, (Modifiers)constructor.Modifiers, false);
                         }
                         CompilerClassLoader.AddDeclaredExceptions(cb, constructor.throws);
                         CodeEmitter ilgen = CodeEmitter.Create(cb);
                         constructor.Emit(classLoader, ilgen);
                         ilgen.DoEmit();
                         if(constructor.Attributes != null)
                         {
                             foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes)
                             {
                                 AttributeHelper.SetCustomAttribute(classLoader, cb, attr);
                             }
                         }
                     }
                 }
                 foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors)
                 {
                     if(constructor.Attributes != null)
                     {
                         foreach(MethodWrapper mw in methods)
                         {
                             if(mw.Name == "<init>" && mw.Signature == constructor.Sig)
                             {
                                 MethodBuilder mb = mw.GetMethod() as MethodBuilder;
                                 if(mb != null)
                                 {
                                     foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes)
                                     {
                                         AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             if(clazz.Methods != null)
             {
                 // HACK this isn't the right place to do this, but for now it suffices
                 foreach(IKVM.Internal.MapXml.Method method in clazz.Methods)
                 {
                     // are we adding a new method?
                     if(GetMethodWrapper(method.Name, method.Sig, false) == null)
                     {
                         if(method.body == null)
                         {
                             Console.Error.WriteLine("Error: Method {0}.{1}{2} in xml remap file doesn't have a body.", clazz.Name, method.Name, method.Sig);
                             continue;
                         }
                         bool setmodifiers = false;
                         MethodAttributes attribs = method.MethodAttributes;
                         MapModifiers(method.Modifiers, false, out setmodifiers, ref attribs);
                         Type returnType;
                         Type[] parameterTypes;
                         MapSignature(method.Sig, out returnType, out parameterTypes);
                         MethodBuilder mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes);
                         if(setmodifiers)
                         {
                             AttributeHelper.SetModifiers(mb, (Modifiers)method.Modifiers, false);
                         }
                         if(method.@override != null)
                         {
                             MethodWrapper mw = GetClassLoader().LoadClassByDottedName([email protected]).GetMethodWrapper([email protected], method.Sig, true);
                             mw.Link();
                             typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod());
                         }
                         CompilerClassLoader.AddDeclaredExceptions(mb, method.throws);
                         CodeEmitter ilgen = CodeEmitter.Create(mb);
                         method.Emit(classLoader, ilgen);
                         ilgen.DoEmit();
                         if(method.Attributes != null)
                         {
                             foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes)
                             {
                                 AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
                             }
                         }
                     }
                 }
                 foreach(IKVM.Internal.MapXml.Method method in clazz.Methods)
                 {
                     if(method.Attributes != null)
                     {
                         foreach(MethodWrapper mw in methods)
                         {
                             if(mw.Name == method.Name && mw.Signature == method.Sig)
                             {
                                 MethodBuilder mb = mw.GetMethod() as MethodBuilder;
                                 if(mb != null)
                                 {
                                     foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes)
                                     {
                                         AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             if(clazz.Interfaces != null)
             {
                 foreach(IKVM.Internal.MapXml.Interface iface in clazz.Interfaces)
                 {
                     TypeWrapper tw = GetClassLoader().LoadClassByDottedName(iface.Name);
                     // NOTE since this interface won't be part of the list in the ImplementAttribute,
                     // it won't be visible from Java that the type implements this interface.
                     typeBuilder.AddInterfaceImplementation(tw.TypeAsBaseType);
                     if(iface.Methods != null)
                     {
                         foreach(IKVM.Internal.MapXml.Method m in iface.Methods)
                         {
                             MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false);
                             if(mw == null)
                             {
                                 throw new InvalidOperationException("Method " + m.Name + m.Sig + " not found in interface " + tw.Name);
                             }
                             mw.Link();
                             MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(this, typeBuilder, tw.Name + "/" + m.Name, MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.CheckAccessOnOverride);
                             AttributeHelper.HideFromJava(mb);
                             typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod());
                             CodeEmitter ilgen = CodeEmitter.Create(mb);
                             m.Emit(classLoader, ilgen);
                             ilgen.DoEmit();
                         }
                     }
                 }
             }
         }
     }
 }
		private static bool GatherAllInterfaceMethods(TypeWrapper tw, ClassFile.ConstantPoolItemMethodType[] bridges, Dictionary<MethodKey, MethodWrapper> methods,
			ref int abstractMethodCount, ref int bridgeMethodCount)
		{
			foreach (MethodWrapper mw in tw.GetMethods())
			{
				if (mw.IsVirtual)
				{
					MirandaMethodWrapper mmw = mw as MirandaMethodWrapper;
					if (mmw != null)
					{
						if (mmw.Error != null)
						{
							return false;
						}
						continue;
					}
					MethodKey key = new MethodKey("", mw.Name, mw.Signature);
					MethodWrapper current;
					if (methods.TryGetValue(key, out current))
					{
						if (!MatchSignatures(mw, current))
						{
							// linkage error (or unloadable type)
							return false;
						}
					}
					else
					{
						methods.Add(key, mw);
						if (mw.IsAbstract && !IsObjectMethod(mw))
						{
							if (bridges != null && IsBridge(mw, bridges))
							{
								bridgeMethodCount++;
							}
							else
							{
								abstractMethodCount++;
							}
						}
					}
					mw.Link();
					if (mw.GetMethod() == null)
					{
						return false;
					}
					if (current != null && mw.RealName != current.RealName)
					{
						return false;
					}
				}
			}
			foreach (TypeWrapper tw1 in tw.Interfaces)
			{
				if (!GatherAllInterfaceMethods(tw1, bridges, methods, ref abstractMethodCount, ref bridgeMethodCount))
				{
					return false;
				}
			}
			return true;
		}
示例#21
0
 internal AotTypeWrapper(ClassFile f, CompilerClassLoader loader)
     : base(f, loader, null)
 {
 }
		private static bool IsBridge(MethodWrapper mw, ClassFile.ConstantPoolItemMethodType[] bridges)
		{
			foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges)
			{
				if (bridge.Signature == mw.Signature)
				{
					return true;
				}
			}
			return false;
		}
示例#23
0
		private static BootstrapMethod[] ReadBootstrapMethods(BigEndianBinaryReader br, ClassFile classFile)
		{
			BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
			ushort count = rdr.ReadUInt16();
			BootstrapMethod[] bsm = new BootstrapMethod[count];
			for(int i = 0; i < bsm.Length; i++)
			{
				ushort bsm_index = rdr.ReadUInt16();
				if(bsm_index >= classFile.constantpool.Length || !(classFile.constantpool[bsm_index] is ConstantPoolItemMethodHandle))
				{
					throw new ClassFormatError("bootstrap_method_index {0} has bad constant type in class file {1}", bsm_index, classFile.Name);
				}
				classFile.MarkLinkRequiredConstantPoolItem(bsm_index);
				ushort argument_count = rdr.ReadUInt16();
				ushort[] args = new ushort[argument_count];
				for(int j = 0; j < args.Length; j++)
				{
					ushort argument_index = rdr.ReadUInt16();
					if(!classFile.IsValidConstant(argument_index))
					{
						throw new ClassFormatError("argument_index {0} has bad constant type in class file {1}", argument_index, classFile.Name);
					}
					classFile.MarkLinkRequiredConstantPoolItem(argument_index);
					args[j] = argument_index;
				}
				bsm[i] = new BootstrapMethod(bsm_index, args);
			}
			if(!rdr.IsAtEnd)
			{
				throw new ClassFormatError("Bad length on BootstrapMethods in class file {0}", classFile.Name);
			}
			return bsm;
		}
		private static bool MatchSignatures(MethodWrapper interfaceMethod, ClassFile.ConstantPoolItemMethodType samMethodType)
		{
			return interfaceMethod.ReturnType == samMethodType.GetRetType()
				&& MatchTypes(interfaceMethod.GetParameters(), samMethodType.GetArgTypes());
		}
示例#25
0
		private static object ReadAnnotation(BigEndianBinaryReader rdr, ClassFile classFile, string[] utf8_cp)
		{
			string type = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16());
			ushort num_element_value_pairs = rdr.ReadUInt16();
			object[] annot = new object[2 + num_element_value_pairs * 2];
			annot[0] = AnnotationDefaultAttribute.TAG_ANNOTATION;
			annot[1] = type;
			for(int i = 0; i < num_element_value_pairs; i++)
			{
				annot[2 + i * 2 + 0] = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16());
				annot[2 + i * 2 + 1] = ReadAnnotationElementValue(rdr, classFile, utf8_cp);
			}
			return annot;
		}
		private static bool IsLambdaMetafactory(ClassFile classFile, ClassFile.BootstrapMethod bsm)
		{
			ClassFile.ConstantPoolItemMethodHandle mh;
			return bsm.ArgumentCount == 3
				&& classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType
				&& classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle
				&& classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType
				&& (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ClassFile.RefKind.invokeStatic
				&& mh.Member != null
				&& IsLambdaMetafactory(mh.Member);
		}
		private TypeWrapper GetTypeWrapperCompilerHook(string name)
		{
			RemapperTypeWrapper rtw;
			if(remapped.TryGetValue(name, out rtw))
			{
				return rtw;
			}
			else
			{
				ClassItem classdef;
				if(classes.TryGetValue(name, out classdef))
				{
					classes.Remove(name);
					ClassFile f;
					try
					{
						ClassFileParseOptions cfp = ClassFileParseOptions.LocalVariableTable;
						if(this.EmitStackTraceInfo)
						{
							cfp |= ClassFileParseOptions.LineNumberTable;
						}
						f = new ClassFile(classdef.data, 0, classdef.data.Length, name, cfp);
					}
					catch(ClassFormatError x)
					{
						StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
						return null;
					}
					if(options.removeUnusedFields)
					{
						f.RemoveUnusedFields();
					}
					if(f.IsPublic && options.privatePackages != null)
					{
						foreach(string p in options.privatePackages)
						{
							if(f.Name.StartsWith(p))
							{
								f.SetInternal();
								break;
							}
						}
					}
					if(f.IsPublic && options.publicPackages != null)
					{
						bool found = false;
						foreach(string package in options.publicPackages)
						{
							if(f.Name.StartsWith(package))
							{
								found = true;
								break;
							}
						}
						if(!found)
						{
							f.SetInternal();
						}
					}
					if(!f.IsInterface
						&& !f.IsAbstract
						&& !f.IsPublic
						&& !f.IsInternal
						&& !f.IsFinal
						&& !baseClasses.ContainsKey(f.Name)
						&& !options.targetIsModule
						&& options.sharedclassloader == null)
					{
						f.SetEffectivelyFinal();
					}
					if(f.SourceFileAttribute != null)
					{
						if(classdef.path != null)
						{
							string sourceFile = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(classdef.path), f.SourceFileAttribute));
							if(File.Exists(sourceFile))
							{
								f.SourcePath = sourceFile;
							}
						}
						if(f.SourcePath == null)
						{
							if (options.sourcepath != null)
							{
								string package = f.Name;
								int index = package.LastIndexOf('.');
								package = index == -1 ? "" : package.Substring(0, index).Replace('.', '/');
								f.SourcePath = Path.GetFullPath(Path.Combine(options.sourcepath + "/" + package, f.SourceFileAttribute));
							}
							else
							{
								f.SourcePath = f.SourceFileAttribute;
							}
						}
					}
					try
					{
						TypeWrapper type = DefineClass(f, null);
						if(f.IKVMAssemblyAttribute != null)
						{
							importedStubTypes.Add(f.Name, type);
						}
						return type;
					}
					catch (ClassFormatError x)
					{
						StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message);
						return null;
					}
					catch (IllegalAccessError x)
					{
						StaticCompiler.IssueMessage(options, Message.IllegalAccessError, name, x.Message);
						return null;
					}
					catch (VerifyError x)
					{
						StaticCompiler.IssueMessage(options, Message.VerificationError, name, x.Message);
						return null;
					}
					catch (NoClassDefFoundError x)
					{
						StaticCompiler.IssueMessage(options, Message.NoClassDefFoundError, name, x.Message);
						return null;
					}
					catch (RetargetableJavaException x)
					{
						StaticCompiler.IssueMessage(options, Message.GenericUnableToCompileError, name, x.GetType().Name, x.Message);
						return null;
					}
				}
				else
				{
					return null;
				}
			}
		}
		private static bool IsLambdaAltMetafactory(ClassFile classFile, ClassFile.BootstrapMethod bsm)
		{
			ClassFile.ConstantPoolItemMethodHandle mh;
			AltFlags flags;
			int argpos = 4;
			return bsm.ArgumentCount >= 4
				&& (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ClassFile.RefKind.invokeStatic
				&& mh.Member != null
				&& IsLambdaAltMetafactory(mh.Member)
				&& classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType
				&& classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle
				&& classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType
				&& classFile.GetConstantPoolConstantType(bsm.GetArgument(3)) == ClassFile.ConstantType.Integer
				&& ((flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3))) & ~AltFlags.Mask) == 0
				&& ((flags & AltFlags.Markers) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.Class, ref argpos))
				&& ((flags & AltFlags.Bridges) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.MethodType, ref argpos))
				&& argpos == bsm.ArgumentCount;
		}
		internal DynamicPropertyFieldWrapper(TypeWrapper declaringType, ClassFile.Field fld)
			: base(declaringType, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal), null)
		{
			getter = GetMethod(fld.PropertyGetter, "()" + fld.Signature, fld.IsStatic);
			setter = GetMethod(fld.PropertySetter, "(" + fld.Signature + ")V", fld.IsStatic);
		}
		private static bool CheckOptionalArgs(ClassFile classFile, ClassFile.BootstrapMethod bsm, ClassFile.ConstantType type, ref int argpos)
		{
			if (bsm.ArgumentCount - argpos < 1)
			{
				return false;
			}
			if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos)) != ClassFile.ConstantType.Integer)
			{
				return false;
			}
			int count = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++));
			if (count < 0 || bsm.ArgumentCount - argpos < count)
			{
				return false;
			}
			for (int i = 0; i < count; i++)
			{
				if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos++)) != type)
				{
					return false;
				}
			}
			return true;
		}