コード例 #1
0
        private SetupStatusEnum LoadOpCodes(string path, out OpCodeWrapper opCodes)
        {
            FileInfo        fileInfo = new FileInfo(path);
            SetupStatusEnum status   = SetupStatusEnum.Idle;

            opCodes = null;
            try
            {
                if (fileInfo.Exists)
                {
                    opCodes = LoadFile(path) as OpCodeWrapper;
                    if (opCodes == null)
                    {
                        status = SetupStatusEnum.Corrupt;
                    }
                    else if (opCodes.CompatibleWith(typeof(T)))
                    {
                        status = SetupStatusEnum.Valid;
                    }
                    else
                    {
                        status = SetupStatusEnum.Incompatible;
                    }
                }
                else
                {
                    status = SetupStatusEnum.Missing;
                }
            }
            catch (System.Exception)
            {
                status = SetupStatusEnum.Corrupt;
            }

            return(status);
        }
コード例 #2
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		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);
					}
				}
			}
		}
コード例 #3
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void OptimizeBranchSizes()
		{
			int offset = 0;
			for (int i = 0; i < code.Count; i++)
			{
				if (code[i].pseudo == CodeType.Label)
				{
					code[i].Label.Temp = offset;
				}
				offset += code[i].Size;
			}
			offset = 0;
			for (int i = 0; i < code.Count; i++)
			{
				int prevOffset = offset;
				offset += code[i].Size;
				if (code[i].HasLabel && code[i].opcode.OperandType == OperandType.InlineBrTarget)
				{
					CodeEmitterLabel label = code[i].Label;
					int diff = label.Temp - (prevOffset + code[i].opcode.Size + 1);
					if (-128 <= diff && diff <= 127)
					{
						OpCode opcode = code[i].opcode;
						if (opcode == OpCodes.Brtrue)
						{
							opcode = OpCodes.Brtrue_S;
						}
						else if (opcode == OpCodes.Brfalse)
						{
							opcode = OpCodes.Brfalse_S;
						}
						else if (opcode == OpCodes.Br)
						{
							opcode = OpCodes.Br_S;
						}
						else if (opcode == OpCodes.Beq)
						{
							opcode = OpCodes.Beq_S;
						}
						else if (opcode == OpCodes.Bne_Un)
						{
							opcode = OpCodes.Bne_Un_S;
						}
						else if (opcode == OpCodes.Ble)
						{
							opcode = OpCodes.Ble_S;
						}
						else if (opcode == OpCodes.Ble_Un)
						{
							opcode = OpCodes.Ble_Un_S;
						}
						else if (opcode == OpCodes.Blt)
						{
							opcode = OpCodes.Blt_S;
						}
						else if (opcode == OpCodes.Blt_Un)
						{
							opcode = OpCodes.Blt_Un_S;
						}
						else if (opcode == OpCodes.Bge)
						{
							opcode = OpCodes.Bge_S;
						}
						else if (opcode == OpCodes.Bge_Un)
						{
							opcode = OpCodes.Bge_Un_S;
						}
						else if (opcode == OpCodes.Bgt)
						{
							opcode = OpCodes.Bgt_S;
						}
						else if (opcode == OpCodes.Bgt_Un)
						{
							opcode = OpCodes.Bgt_Un_S;
						}
						else if (opcode == OpCodes.Leave)
						{
							opcode = OpCodes.Leave_S;
						}
						code[i] = new OpCodeWrapper(opcode, label);
					}
				}
			}
		}
コード例 #4
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void AnnihilateStoreReleaseTempLocals()
		{
			for (int i = 1; i < code.Count; i++)
			{
				if (code[i].opcode == OpCodes.Stloc)
				{
					if (code[i + 1].pseudo == CodeType.ReleaseTempLocal
						&& code[i].Local == code[i + 1].Local)
					{
						code[i] = new OpCodeWrapper(OpCodes.Pop, null);
					}
					else if (code[i + 1].opcode == OpCodes.Ldloc
						&& code[i + 1].Local == code[i].Local
						&& code[i + 2].pseudo == CodeType.ReleaseTempLocal
						&& code[i + 2].Local == code[i].Local)
					{
						code.RemoveRange(i, 2);
					}
				}
			}
		}
コード例 #5
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
			internal bool MatchLocal(OpCodeWrapper other)
			{
				return data == other.data;
			}
コード例 #6
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void CLRv4_x64_JIT_Workaround()
		{
			for (int i = 0; i < code.Count - 2; i++)
			{
				// This is a workaround for https://connect.microsoft.com/VisualStudio/feedback/details/566946/x64-jit-optimization-bug
				// 
				// Testing shows that the bug appears to be very specific and requires a comparison of a method argument with zero.
				// For example, the problem goes away when the method argument is first assigned to a local variable and then
				// the comparison (and subsequent use) is done against the local variable.
				//
				// This means we only have to detect these specific patterns:
				//
				//   ldc.i8 0x0        ldarg
				//   ldarg             ldc.i8 0x0
				//   beq/bne           beq/bne
				//
				// The workaround is to replace ldarg with ldarga/ldind.i8. Looking at the generated code by the x86 and x64 JITs
				// this appears to be as efficient as the ldarg and it avoids the x64 bug.
				if (code[i].opcode == OpCodes.Ldc_I8 && code[i].ValueInt64 == 0)
				{
					short arg;
					int m;
					if (i > 0 && MatchLdarg(code[i - 1], out arg) && IsBranchEqNe(code[i + 1].opcode))
					{
						m = i - 1;
					}
					else if (MatchLdarg(code[i + 1], out arg) && IsBranchEqNe(code[i + 2].opcode))
					{
						m = i + 1;
					}
					else
					{
						continue;
					}
					code[m] = new OpCodeWrapper(OpCodes.Ldarga, arg);
					code.Insert(m + 1, new OpCodeWrapper(OpCodes.Ldind_I8, null));
				}
			}
		}
コード例 #7
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private static bool MatchLdarg(OpCodeWrapper opc, out short arg)
		{
			if (opc.opcode == OpCodes.Ldarg)
			{
				arg = opc.ValueInt16;
				return true;
			}
			else if (opc.opcode == OpCodes.Ldarg_S)
			{
				arg = opc.ValueByte;
				return true;
			}
			else if (opc.opcode == OpCodes.Ldarg_0)
			{
				arg = 0;
				return true;
			}
			else if (opc.opcode == OpCodes.Ldarg_1)
			{
				arg = 1;
				return true;
			}
			else if (opc.opcode == OpCodes.Ldarg_2)
			{
				arg = 2;
				return true;
			}
			else if (opc.opcode == OpCodes.Ldarg_3)
			{
				arg = 3;
				return true;
			}
			else
			{
				arg = -1;
				return false;
			}
		}
コード例 #8
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void ConvertSynchronizedFaultToFinally()
		{
			bool labelIndexSet = false;
			int start = -1;
			int nest = 0;
			int next = -1;
			for (int i = 0; i < code.Count; i++)
			{
				switch (code[i].pseudo)
				{
					case CodeType.BeginExceptionBlock:
						if (nest == 0)
						{
							start = i;
						}
						else if (nest == 1 && next <= start)
						{
							next = i;
						}
						nest++;
						break;
					case CodeType.BeginCatchBlock:
					case CodeType.BeginFinallyBlock:
						if (nest == 1)
						{
							nest = 0;
							if (next > start)
							{
								// while we were processing the outer block, we encountered a nested BeginExceptionBlock
								// so now that we've failed the outer, restart at the first nested block
								i = start = next;
								nest = 1;
							}
						}
						else
						{
							next = -1;
						}
						break;
					case CodeType.BeginFaultBlock:
						if (nest == 1)
						{
							int beginFault = i;
							if (code[i + 1].pseudo == CodeType.LineNumber)
							{
								i++;
							}
							// check if the fault handler is the synchronized block exit pattern
							if (code[i + 1].opcode == OpCodes.Ldloc
								&& code[i + 2].pseudo == CodeType.MonitorExit
								&& code[i + 3].opcode == OpCodes.Endfinally)
							{
								if (!labelIndexSet)
								{
									labelIndexSet = true;
									SetLabelIndexes();
								}
								// now make two passes through the try block to 1) see if all leave
								// opcodes that leave the try block do a synchronized block exit
								// and 2) patch out the synchronized block exit
								for (int pass = 0; pass < 2; pass++)
								{
									for (int j = start; j < i; j++)
									{
										if (code[j].opcode == OpCodes.Leave)
										{
											int target = code[j].Label.Temp;
											if (target < start || target > i)
											{
												// check if the code preceding the leave matches the fault block
												if ((code[j - 1].opcode == OpCodes.Pop || code[j - 1].opcode == OpCodes.Stloc)
													&& code[j - 2].pseudo == CodeType.MonitorExit
													&& code[j - 3].Match(code[i + 1]))
												{
													if (pass == 1)
													{
														// move the leave to the top of the sequence we're removing
														code[j - 3] = code[j - 1];
														code[j - 2] = code[j - 0];
														code[j - 1] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None);
														code[j - 0] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None);
													}
												}
												else if (code[j - 1].pseudo == CodeType.MonitorExit
													&& code[j - 2].Match(code[i + 1]))
												{
													if (pass == 1)
													{
														// move the leave to the top of the sequence we're removing
														code[j - 2] = code[j];
														code[j - 1] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None);
														code[j - 0] = new OpCodeWrapper(CodeType.Unreachable, CodeTypeFlags.None);
													}
												}
												else
												{
													goto fail;
												}
											}
										}
									}
								}
								// if we end up here, all leaves have been successfully patched,
								// so now we turn the BeginFaultBlock into a BeginFinallyBlock
								code[beginFault] = new OpCodeWrapper(CodeType.BeginFinallyBlock, CodeTypeFlags.None);
							fail: ;
							}
							goto case CodeType.BeginFinallyBlock;
						}
						break;
					case CodeType.EndExceptionBlock:
						nest--;
						break;
				}
			}
		}
コード例 #9
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
			internal bool Match(OpCodeWrapper other)
			{
				return other.pseudo == pseudo
					&& other.opcode == opcode
					&& (other.data == data || (data != null && data.Equals(other.data)));
			}
コード例 #10
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void MergeExceptionBlocks()
		{
			// The first loop will convert all Begin[Exception|Catch|Fault|Finally]Block and EndExceptionBlock
			// pseudo opcodes into a cyclic linked list (EndExceptionBlock links back to BeginExceptionBlock)
			// to allow for easy traversal in the next loop.
			int[] extra = new int[code.Count];
			Stack<int> stack = new Stack<int>();
			int currentBeginExceptionBlock = -1;
			int currentLast = -1;
			for (int i = 0; i < code.Count; i++)
			{
				switch (code[i].pseudo)
				{
					case CodeType.BeginExceptionBlock:
						stack.Push(currentBeginExceptionBlock);
						currentBeginExceptionBlock = i;
						currentLast = i;
						break;
					case CodeType.EndExceptionBlock:
						extra[currentLast] = i;
						extra[i] = currentBeginExceptionBlock;
						currentBeginExceptionBlock = stack.Pop();
						currentLast = currentBeginExceptionBlock;
						if (currentLast != -1)
						{
							while (extra[currentLast] != 0)
							{
								currentLast = extra[currentLast];
							}
						}
						break;
					case CodeType.BeginCatchBlock:
					case CodeType.BeginFaultBlock:
					case CodeType.BeginFinallyBlock:
						extra[currentLast] = i;
						currentLast = i;
						break;
				}
			}

			// Now we look for consecutive exception blocks that have the same fault handler
			for (int i = 0; i < code.Count - 1; i++)
			{
				if (code[i].pseudo == CodeType.EndExceptionBlock
					&& code[i + 1].pseudo == CodeType.BeginExceptionBlock)
				{
					if (IsFaultOnlyBlock(extra, extra[i]) && IsFaultOnlyBlock(extra, i + 1))
					{
						int beginFault1 = extra[extra[i]];
						int beginFault2 = extra[i + 1];
						int length1 = extra[beginFault1] - beginFault1;
						int length2 = extra[beginFault2] - beginFault2;
						if (length1 == length2 && MatchHandlers(beginFault1, beginFault2, length1))
						{
							// Check if the labels at the start of the handler are reachable from outside
							// of the new combined block.
							for (int j = i + 2; j < beginFault2; j++)
							{
								if (code[j].pseudo == CodeType.OpCode)
								{
									break;
								}
								else if (code[j].pseudo == CodeType.Label)
								{
									if (HasBranchTo(0, extra[i], code[j].Label)
										|| HasBranchTo(beginFault2 + length2, code.Count, code[j].Label))
									{
										goto no_merge;
									}
								}
							}
							// Merge the two blocks by overwritting the first fault block and
							// the BeginExceptionBlock of the second block.
							for (int j = beginFault1; j < i + 2; j++)
							{
								code[j] = new OpCodeWrapper(OpCodes.Nop, null);
							}
							// Repair the linking structure.
							extra[extra[i]] = beginFault2;
							extra[extra[beginFault2]] = extra[i];
						}
					}
				no_merge: ;
				}
			}
		}
コード例 #11
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void DeduplicateBranchSourceTargetCode()
		{
			SetLabelIndexes();
			for (int i = 0; i < code.Count; i++)
			{
				if (code[i].opcode == OpCodes.Br && code[i].HasLabel)
				{
					int source = i - 1;
					int target = code[i].Label.Temp - 1;
					while (source >= 0 && target >= 0)
					{
						switch (code[source].pseudo)
						{
							case CodeType.LineNumber:
							case CodeType.OpCode:
								break;
							default:
								goto break_while;
						}
						if (!code[source].Match(code[target]))
						{
							break;
						}
						switch (code[source].opcode.FlowControl)
						{
							case FlowControl.Branch:
							case FlowControl.Cond_Branch:
								goto break_while;
						}
						source--;
						target--;
					}
				break_while: ;
					source++;
					target++;
					if (source != i && target > 0 && source != target - 1)
					{
						// TODO for now we only do this optimization if there happens to be an appriopriate label
						if (code[target - 1].pseudo == CodeType.Label)
						{
							code[source] = new OpCodeWrapper(OpCodes.Br, code[target - 1].Label);
							for (int j = source + 1; j <= i; j++)
							{
								// We can't depend on DCE for code correctness (we have to maintain all MSIL invariants at all times),
								// so we patch out the unused code.
								code[j] = new OpCodeWrapper(CodeType.Unreachable, null);
							}
						}
					}
				}
			}
		}
コード例 #12
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void ChaseBranches()
		{
			/*
			 * Here we do a couple of different optimizations to unconditional branches:
			 *  - a branch to a ret or endfinally will be replaced
			 *    by the ret or endfinally instruction (because that is always at least as efficient)
			 *  - a branch to a branch will remove the indirection
			 *  - a leave to a branch or leave will remove the indirection
			 */
			SetLabelIndexes();
			for (int i = 0; i < code.Count; i++)
			{
				if (code[i].opcode == OpCodes.Br)
				{
					int target = code[i].Label.Temp + 1;
					if (code[target].pseudo == CodeType.LineNumber)
					{
						// line number info on endfinally or ret is probably useless anyway
						target++;
					}
					if (code[target].opcode == OpCodes.Endfinally || code[target].opcode == OpCodes.Ret)
					{
						code[i] = code[target];
					}
					else
					{
						CodeEmitterLabel label = null;
						while (code[target].opcode == OpCodes.Br && target != i)
						{
							label = code[target].Label;
							target = code[target].Label.Temp + 1;
						}
						if (label != null)
						{
							code[i] = new OpCodeWrapper(OpCodes.Br, label);
						}
					}
				}
				else if (code[i].opcode == OpCodes.Leave)
				{
					int target = code[i].Label.Temp + 1;
					CodeEmitterLabel label = null;
					while ((code[target].opcode == OpCodes.Br || code[target].opcode == OpCodes.Leave) && target != i)
					{
						label = code[target].Label;
						target = code[target].Label.Temp + 1;
					}
					if (label != null)
					{
						code[i] = new OpCodeWrapper(OpCodes.Leave, label);
					}
				}
			}
		}
コード例 #13
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void OptimizeLdcI8(int index)
		{
			long value = code[index].ValueInt64;
			OpCode opc = OpCodes.Nop;
			switch (value)
			{
				case -1:
					opc = OpCodes.Ldc_I4_M1;
					break;
				case 0:
					opc = OpCodes.Ldc_I4_0;
					break;
				case 1:
					opc = OpCodes.Ldc_I4_1;
					break;
				case 2:
					opc = OpCodes.Ldc_I4_2;
					break;
				case 3:
					opc = OpCodes.Ldc_I4_3;
					break;
				case 4:
					opc = OpCodes.Ldc_I4_4;
					break;
				case 5:
					opc = OpCodes.Ldc_I4_5;
					break;
				case 6:
					opc = OpCodes.Ldc_I4_6;
					break;
				case 7:
					opc = OpCodes.Ldc_I4_7;
					break;
				case 8:
					opc = OpCodes.Ldc_I4_8;
					break;
				default:
					if (value >= -2147483648L && value <= 4294967295L)
					{
						if (value >= -128 && value <= 127)
						{
							code[index] = new OpCodeWrapper(OpCodes.Ldc_I4_S, (sbyte)value);
						}
						else
						{
							code[index] = new OpCodeWrapper(OpCodes.Ldc_I4, (int)value);
						}
						if (value < 0)
						{
							code.Insert(index + 1, new OpCodeWrapper(OpCodes.Conv_I8, null));
						}
						else
						{
							code.Insert(index + 1, new OpCodeWrapper(OpCodes.Conv_U8, null));
						}
					}
					break;
			}
			if (opc != OpCodes.Nop)
			{
				code[index] = new OpCodeWrapper(opc, null);
				code.Insert(index + 1, new OpCodeWrapper(OpCodes.Conv_I8, null));
			}
		}
コード例 #14
0
ファイル: CodeEmitter.cs プロジェクト: Semogj/ikvm-fork
		private void PatchCompare(int index, OpCode ble, OpCode blt, OpCode bge, OpCode bgt)
		{
			if (code[index + 11].opcode == OpCodes.Brtrue)
			{
				code[index] = new OpCodeWrapper(OpCodes.Bne_Un, code[index + 11].Label);
				code.RemoveRange(index + 1, 11);
			}
			else if (code[index + 11].opcode == OpCodes.Brfalse)
			{
				code[index] = new OpCodeWrapper(OpCodes.Beq, code[index + 11].Label);
				code.RemoveRange(index + 1, 11);
			}
			else if (code[index + 11].opcode == OpCodes.Ldc_I4_0)
			{
				if (code[index + 12].opcode == OpCodes.Ble)
				{
					code[index] = new OpCodeWrapper(ble, code[index + 12].Label);
					code.RemoveRange(index + 1, 12);
				}
				else if (code[index + 12].opcode == OpCodes.Blt)
				{
					code[index] = new OpCodeWrapper(blt, code[index + 12].Label);
					code.RemoveRange(index + 1, 12);
				}
				else if (code[index + 12].opcode == OpCodes.Bge)
				{
					code[index] = new OpCodeWrapper(bge, code[index + 12].Label);
					code.RemoveRange(index + 1, 12);
				}
				else if (code[index + 12].opcode == OpCodes.Bgt)
				{
					code[index] = new OpCodeWrapper(bgt, code[index + 12].Label);
					code.RemoveRange(index + 1, 12);
				}
			}
		}
コード例 #15
0
ファイル: GenericDevice.cs プロジェクト: zaksie/nimbo
 internal virtual void ReplaceOpCodeWrapper(OpCodeWrapper newOpCodes)
 {
     OpCodes.Dispose();
     newOpCodes.Initialize(this);
     //implementing classes must carry out the substitution
 }