Esempio n. 1
0
		internal void Emit(OpCode opcode, CodeEmitterLocal local)
		{
			EmitOpCode(opcode, local);
		}
Esempio n. 2
0
		private void OptimizePatterns()
		{
			SetLabelRefCounts();
			for (int i = 1; i < code.Count; i++)
			{
				if (code[i].opcode == OpCodes.Isinst
					&& code[i + 1].opcode == OpCodes.Ldnull
					&& code[i + 2].opcode == OpCodes.Cgt_Un
					&& (code[i + 3].opcode == OpCodes.Brfalse || code[i + 3].opcode == OpCodes.Brtrue))
				{
					code.RemoveRange(i + 1, 2);
				}
				else if (code[i].opcode == OpCodes.Ldelem_I1
					&& code[i + 1].opcode == OpCodes.Ldc_I4 && code[i + 1].ValueInt32 == 255
					&& code[i + 2].opcode == OpCodes.And)
				{
					code[i] = new OpCodeWrapper(OpCodes.Ldelem_U1, null);
					code.RemoveRange(i + 1, 2);
				}
				else if (code[i].opcode == OpCodes.Ldelem_I1
					&& code[i + 1].opcode == OpCodes.Conv_I8
					&& code[i + 2].opcode == OpCodes.Ldc_I8 && code[i + 2].ValueInt64 == 255
					&& code[i + 3].opcode == OpCodes.And)
				{
					code[i] = new OpCodeWrapper(OpCodes.Ldelem_U1, null);
					code.RemoveRange(i + 2, 2);
				}
				else if (code[i].opcode == OpCodes.Ldc_I4
					&& code[i + 1].opcode == OpCodes.Ldc_I4
					&& code[i + 2].opcode == OpCodes.And)
				{
					code[i] = new OpCodeWrapper(OpCodes.Ldc_I4, code[i].ValueInt32 & code[i + 1].ValueInt32);
					code.RemoveRange(i + 1, 2);
				}
				else if (MatchCompare(i, OpCodes.Cgt, OpCodes.Clt_Un, Types.Double)		// dcmpl
					|| MatchCompare(i, OpCodes.Cgt, OpCodes.Clt_Un, Types.Single))		// fcmpl
				{
					PatchCompare(i, OpCodes.Ble_Un, OpCodes.Blt_Un, OpCodes.Bge, OpCodes.Bgt);
				}
				else if (MatchCompare(i, OpCodes.Cgt_Un, OpCodes.Clt, Types.Double)		// dcmpg
					|| MatchCompare(i, OpCodes.Cgt_Un, OpCodes.Clt, Types.Single))		// fcmpg
				{
					PatchCompare(i, OpCodes.Ble, OpCodes.Blt, OpCodes.Bge_Un, OpCodes.Bgt_Un);
				}
				else if (MatchCompare(i, OpCodes.Cgt, OpCodes.Clt, Types.Int64))		// lcmp
				{
					PatchCompare(i, OpCodes.Ble, OpCodes.Blt, OpCodes.Bge, OpCodes.Bgt);
				}
				else if (i < code.Count - 10
					&& code[i].opcode == OpCodes.Ldc_I4
					&& code[i + 1].opcode == OpCodes.Dup
					&& code[i + 2].opcode == OpCodes.Ldc_I4_M1
					&& code[i + 3].opcode == OpCodes.Bne_Un
					&& code[i + 4].opcode == OpCodes.Pop
					&& code[i + 5].opcode == OpCodes.Neg
					&& code[i + 6].opcode == OpCodes.Br
					&& code[i + 7].pseudo == CodeType.Label && code[i + 7].MatchLabel(code[i + 3]) && code[i + 7].Label.Temp == 1
					&& code[i + 8].opcode == OpCodes.Div
					&& code[i + 9].pseudo == CodeType.Label && code[i + 9].Label == code[i + 6].Label && code[i + 9].Label.Temp == 1)
				{
					int divisor = code[i].ValueInt32;
					if (divisor == -1)
					{
						code[i] = code[i + 5];
						code.RemoveRange(i + 1, 9);
					}
					else
					{
						code[i + 1] = code[i + 8];
						code.RemoveRange(i + 2, 8);
					}
				}
				else if (i < code.Count - 11
					&& code[i].opcode == OpCodes.Ldc_I8
					&& code[i + 1].opcode == OpCodes.Dup
					&& code[i + 2].opcode == OpCodes.Ldc_I4_M1
					&& code[i + 3].opcode == OpCodes.Conv_I8
					&& code[i + 4].opcode == OpCodes.Bne_Un
					&& code[i + 5].opcode == OpCodes.Pop
					&& code[i + 6].opcode == OpCodes.Neg
					&& code[i + 7].opcode == OpCodes.Br
					&& code[i + 8].pseudo == CodeType.Label && code[i + 8].MatchLabel(code[i + 4]) && code[i + 8].Label.Temp == 1
					&& code[i + 9].opcode == OpCodes.Div
					&& code[i + 10].pseudo == CodeType.Label && code[i + 10].MatchLabel(code[i + 7]) && code[i + 10].Label.Temp == 1)
				{
					long divisor = code[i].ValueInt64;
					if (divisor == -1)
					{
						code[i] = code[i + 6];
						code.RemoveRange(i + 1, 10);
					}
					else
					{
						code[i + 1] = code[i + 9];
						code.RemoveRange(i + 2, 9);
					}
				}
				else if (code[i].opcode == OpCodes.Box
					&& code[i + 1].opcode == OpCodes.Unbox && code[i + 1].Type == code[i].Type)
				{
					CodeEmitterLocal local = new CodeEmitterLocal(code[i].Type);
					code[i] = new OpCodeWrapper(OpCodes.Stloc, local);
					code[i + 1] = new OpCodeWrapper(OpCodes.Ldloca, local);
				}
				else if (i < code.Count - 13
					&& code[i + 0].opcode == OpCodes.Box
					&& code[i + 1].opcode == OpCodes.Dup
					&& code[i + 2].opcode == OpCodes.Brtrue
					&& code[i + 3].opcode == OpCodes.Pop
					&& code[i + 4].opcode == OpCodes.Ldloca && code[i + 4].Local.LocalType == code[i + 0].Type
					&& code[i + 5].opcode == OpCodes.Initobj && code[i + 5].Type == code[i + 0].Type
					&& code[i + 6].opcode == OpCodes.Ldloc && code[i + 6].Local == code[i + 4].Local
					&& code[i + 7].pseudo == CodeType.ReleaseTempLocal && code[i + 7].Local == code[i + 6].Local
					&& code[i + 8].opcode == OpCodes.Br
					&& code[i + 9].pseudo == CodeType.Label && code[i + 9].MatchLabel(code[i + 2]) && code[i + 9].Label.Temp == 1
					&& code[i + 10].opcode == OpCodes.Unbox && code[i + 10].Type == code[i + 0].Type
					&& code[i + 11].opcode == OpCodes.Ldobj && code[i + 11].Type == code[i + 0].Type
					&& code[i + 12].pseudo == CodeType.Label && code[i + 12].MatchLabel(code[i + 8]) && code[i + 12].Label.Temp == 1)
				{
					code.RemoveRange(i, 13);
				}

				// NOTE intentionally not an else, because we want to optimize the code generated by the earlier compare optimization
				if (i < code.Count - 6
					&& code[i].opcode.FlowControl == FlowControl.Cond_Branch
					&& code[i + 1].opcode == OpCodes.Ldc_I4 && code[i + 1].ValueInt32 == 1
					&& code[i + 2].opcode == OpCodes.Br
					&& code[i + 3].pseudo == CodeType.Label && code[i + 3].MatchLabel(code[i]) && code[i + 3].Label.Temp == 1
					&& code[i + 4].opcode == OpCodes.Ldc_I4 && code[i + 4].ValueInt32 == 0
					&& code[i + 5].pseudo == CodeType.Label && code[i + 5].MatchLabel(code[i + 2]) && code[i + 5].Label.Temp == 1)
				{
					if (code[i].opcode == OpCodes.Bne_Un)
					{
						code[i] = new OpCodeWrapper(OpCodes.Ceq, null);
						code.RemoveRange(i + 1, 5);
					}
					else if (code[i].opcode == OpCodes.Beq)
					{
						code[i + 0] = new OpCodeWrapper(OpCodes.Ceq, null);
						code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
						code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
						code.RemoveRange(i + 3, 3);
					}
					else if (code[i].opcode == OpCodes.Ble || code[i].opcode == OpCodes.Ble_Un)
					{
						code[i] = new OpCodeWrapper(OpCodes.Cgt, null);
						code.RemoveRange(i + 1, 5);
					}
					else if (code[i].opcode == OpCodes.Blt)
					{
						code[i] = new OpCodeWrapper(OpCodes.Clt, null);
						code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
						code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
						code.RemoveRange(i + 3, 3);
					}
					else if (code[i].opcode == OpCodes.Blt_Un)
					{
						code[i] = new OpCodeWrapper(OpCodes.Clt_Un, null);
						code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
						code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
						code.RemoveRange(i + 3, 3);
					}
					else if (code[i].opcode == OpCodes.Bge || code[i].opcode == OpCodes.Bge_Un)
					{
						code[i] = new OpCodeWrapper(OpCodes.Clt, null);
						code.RemoveRange(i + 1, 5);
					}
					else if (code[i].opcode == OpCodes.Bgt)
					{
						code[i] = new OpCodeWrapper(OpCodes.Cgt, null);
						code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
						code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
						code.RemoveRange(i + 3, 3);
					}
					else if (code[i].opcode == OpCodes.Bgt_Un)
					{
						code[i] = new OpCodeWrapper(OpCodes.Cgt_Un, null);
						code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
						code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
						code.RemoveRange(i + 3, 3);
					}
				}
			}
		}
Esempio n. 3
0
		internal CodeEmitterLocal DeclareLocal(Type localType)
		{
			CodeEmitterLocal local = new CodeEmitterLocal(localType);
			EmitPseudoOpCode(CodeType.DeclareLocal, local);
			return local;
		}
Esempio n. 4
0
		internal void ReleaseTempLocal(CodeEmitterLocal lb)
		{
			EmitPseudoOpCode(CodeType.ReleaseTempLocal, lb);
			for (int i = 0; i < tempLocals.Length; i++)
			{
				if (tempLocals[i] == null)
				{
					tempLocals[i] = lb;
					break;
				}
			}
		}
Esempio n. 5
0
		private int FindLocal(CodeEmitterLocal local)
		{
			for (int i = 0; i < code.Count; i++)
			{
				if (code[i].pseudo == CodeType.DeclareLocal && code[i].Local == local)
				{
					return i;
				}
			}
			// if the local variable isn't declared, it is a temporary that is allocated on demand
			// (so we can move their usage freely)
			return 0;
		}
Esempio n. 6
0
			private void ConvertByRefArgs(CodeEmitter ilgen)
			{
				CodeEmitterLocal[] locals = new CodeEmitterLocal[args.Length];
				for (int i = args.Length - 1; i >= 0; i--)
				{
					Type type = args[i];
					if (type.IsByRef)
					{
						type = ArrayTypeWrapper.MakeArrayType(type.GetElementType(), 1);
					}
					locals[i] = ilgen.DeclareLocal(type);
					ilgen.Emit(OpCodes.Stloc, locals[i]);
				}
				for (int i = 0; i < args.Length; i++)
				{
					ilgen.Emit(OpCodes.Ldloc, locals[i]);
					if (args[i].IsByRef)
					{
						ilgen.Emit(OpCodes.Ldc_I4_0);
						ilgen.Emit(OpCodes.Ldelema, args[i].GetElementType());
					}
				}
			}
Esempio n. 7
0
		internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen)
		{
			Debug.Assert(Name != null);
			if(Name == ".ctor")
			{
				Debug.Assert(Class == null && type != null);
				Type[] argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
				ConstructorInfo ci = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null);
				if(ci == null)
				{
					throw new InvalidOperationException("Missing .ctor: " + type + "..ctor" + Sig);
				}
				ilgen.Emit(opcode, ci);
			}
			else
			{
				Debug.Assert(Class == null ^ type == null);
				if(Class != null)
				{
					Debug.Assert(Sig != null);
					MethodWrapper method = context.ClassLoader.LoadClassByDottedName(Class).GetMethodWrapper(Name, Sig, false);
					if(method == null)
					{
						throw new InvalidOperationException("method not found: " + Class + "." + Name + Sig);
					}
					method.Link();
					// TODO this code is part of what Compiler.CastInterfaceArgs (in compiler.cs) does,
					// it would be nice if we could avoid this duplication...
					TypeWrapper[] argTypeWrappers = method.GetParameters();
					for(int i = 0; i < argTypeWrappers.Length; i++)
					{
						if(argTypeWrappers[i].IsGhost)
						{
							CodeEmitterLocal[] temps = new CodeEmitterLocal[argTypeWrappers.Length + (method.IsStatic ? 0 : 1)];
							for(int j = temps.Length - 1; j >= 0; j--)
							{
								TypeWrapper tw;
								if(method.IsStatic)
								{
									tw = argTypeWrappers[j];
								}
								else
								{
									if(j == 0)
									{
										tw = method.DeclaringType;
									}
									else
									{
										tw = argTypeWrappers[j - 1];
									}
								}
								if(tw.IsGhost)
								{
									tw.EmitConvStackTypeToSignatureType(ilgen, null);
								}
								temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType);
								ilgen.Emit(OpCodes.Stloc, temps[j]);
							}
							for(int j = 0; j < temps.Length; j++)
							{
								ilgen.Emit(OpCodes.Ldloc, temps[j]);
							}
							break;
						}
					}
					if(opcode.Value == OpCodes.Call.Value)
					{
						method.EmitCall(ilgen);
					}
					else if(opcode.Value == OpCodes.Callvirt.Value)
					{
						method.EmitCallvirt(ilgen);
					}
					else if(opcode.Value == OpCodes.Newobj.Value)
					{
						method.EmitNewobj(ilgen);
					}
					else
					{
						// ldftn or ldvirtftn
						ilgen.Emit(opcode, (MethodInfo)method.GetMethod());
					}
				}
				else
				{
					Type[] argTypes;
					if(Sig.StartsWith("("))
					{
						argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
					}
					else if(Sig == "")
					{
						argTypes = Type.EmptyTypes;
					}
					else
					{
						string[] types = Sig.Split(';');
						argTypes = new Type[types.Length];
						for(int i = 0; i < types.Length; i++)
						{
							argTypes[i] = StaticCompiler.GetTypeForMapXml(context.ClassLoader, types[i]);
						}
					}
					MethodInfo mi = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null);
					if(mi == null)
					{
						throw new InvalidOperationException("Missing method: " + type + "." + Name + Sig);
					}
					ilgen.Emit(opcode, mi);
				}
			}
		}