/// <summary> /// </summary> /// <param name="opCode"> /// </param> /// <param name="baseWriter"> /// </param> /// <returns> /// </returns> public static IType GetLocalType(this OpCodePart opCode, BaseWriter baseWriter) { var asString = opCode.ToCode().ToString(); var index = -1; if (opCode.Any(Code.Ldloc_S, Code.Ldloc, Code.Ldloca_S, Code.Ldloca) || opCode.Any(Code.Stloc_S, Code.Stloc)) { index = (opCode as OpCodeInt32Part).Operand; } else { index = int.Parse(asString.Substring(asString.Length - 1)); } Debug.Assert(baseWriter.LocalInfo.Length > index); var localType = baseWriter.LocalInfo[index].LocalType; return(localType); }
/// <summary> /// </summary> /// <param name="opCode"> /// </param> /// <returns> /// </returns> public static int GetArgIndex(this OpCodePart opCode) { var asString = opCode.ToCode().ToString(); var index = -1; if (opCode.Any(Code.Ldarg_S, Code.Ldarg, Code.Ldarga_S, Code.Ldarga, Code.Starg_S, Code.Starg)) { var opCodeInt32 = opCode as OpCodeInt32Part; index = opCodeInt32.Operand; } else { index = int.Parse(asString.Substring(asString.Length - 1)); } return(index); }
private static bool JumpOrLabelPoint(OpCodePart current, out bool startOrEnd) { if ((current.OpCode.FlowControl == FlowControl.Cond_Branch || current.OpCode.FlowControl == FlowControl.Branch) && !current.Any(Code.Leave, Code.Leave_S)) { startOrEnd = false; return(true); } if (current.JumpDestination != null && current.JumpDestination.Any()) { startOrEnd = true; return(true); } startOrEnd = false; return(false); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="exceptionHandlingClause"> /// </param> /// <param name="upperLevelExceptionHandlingClause"> /// </param> public static void WriteCatchEnd( this LlvmWriter llvmWriter, OpCodePart opCode, CatchOfFinallyClause exceptionHandlingClause, CatchOfFinallyClause upperLevelExceptionHandlingClause) { var writer = llvmWriter.Output; var isFinally = exceptionHandlingClause.Flags.HasFlag(ExceptionHandlingClauseOptions.Finally); if (isFinally) { writer.WriteLine("; End of Finally Handler Body"); } else { writer.WriteLine("; End of Catch Handler Body"); } if (isFinally) { // process Leave jumps var index = 0; var opCodeNope = OpCodePart.CreateNop; var fullyDefinedRef = new FullyDefinedReference( string.Concat("%.finally_jump", exceptionHandlingClause.Offset), llvmWriter.System.System_Int32); llvmWriter.WriteLlvmLoad(opCodeNope, llvmWriter.System.System_Int32, fullyDefinedRef); writer.WriteLine(string.Empty); writer.WriteLine( "switch i32 {1}, label %.finally_exit{0} [", exceptionHandlingClause.Offset, opCodeNope.Result); writer.Indent++; writer.WriteLine("i32 {0}, label %.finally_exit{1}", index++, exceptionHandlingClause.Offset); foreach (var leave in exceptionHandlingClause.FinallyJumps) { writer.WriteLine("i32 {0}, label %{1}", index++, leave); } writer.Indent--; writer.WriteLine("]"); llvmWriter.WriteLabel(writer, string.Concat(".finally_exit", exceptionHandlingClause.Offset)); if (exceptionHandlingClause.EmptyFinallyRethrowRequired) { // rethrow exception in empty finally block var opCodeNop = OpCodePart.CreateNop; llvmWriter.WriteRethrow( opCodeNop, upperLevelExceptionHandlingClause, llvmWriter.tryScopes.Count > 0 ? llvmWriter.tryScopes.Peek().Catches.First() : null); } } var startOfHandlerAddress = exceptionHandlingClause.Offset; var endOfHandlerAddress = exceptionHandlingClause.Offset + exceptionHandlingClause.Length; if (exceptionHandlingClause.RethrowCatchWithCleanUpRequired) { llvmWriter.WriteLabel( writer, string.Format(".catch_with_cleanup_{0}_{1}", startOfHandlerAddress, endOfHandlerAddress)); var opCodeNop = OpCodePart.CreateNop; llvmWriter.WriteLandingPad( opCodeNop, LandingPadOptions.Cleanup, null, new[] { upperLevelExceptionHandlingClause != null ? upperLevelExceptionHandlingClause.Catch : llvmWriter.System.System_Exception }); writer.WriteLine(string.Empty); } else { writer.WriteLine("store i32 0, i32* %.error_typeid"); } writer.WriteLine("call void @__cxa_end_catch()"); if (!exceptionHandlingClause.RethrowCatchWithCleanUpRequired || upperLevelExceptionHandlingClause == null) { var isLeave = opCode.Any(Code.Leave, Code.Leave_S); var nextOp = opCode.Next; if (!isLeave && (nextOp == null || nextOp.JumpDestination == null || !nextOp.JumpDestination.Any() || nextOp.GroupAddressStart != endOfHandlerAddress)) { var noNext = nextOp == null; var isNextCatchBlock = nextOp != null && nextOp.CatchOrFinallyBegin != null; var hasExit = llvmWriter.OpsByAddressStart.Values.Any(op => op.ToCode() == Code.Ret); if (!isNextCatchBlock && !noNext && (isLeave || hasExit)) { writer.WriteLine("br label %.exit{0}", endOfHandlerAddress); llvmWriter.WriteLabel(writer, string.Concat(".exit", endOfHandlerAddress)); writer.WriteLine(string.Empty); } else { writer.WriteLine("unreachable"); } } else { if (isLeave) { writer.WriteLine("br label %.a{0}", opCode.JumpAddress()); } else { writer.WriteLine("br label %.a{0}", nextOp.GroupAddressStart); } } } else { if (!upperLevelExceptionHandlingClause.Flags.HasFlag(ExceptionHandlingClauseOptions.Finally)) { writer.WriteLine("br label %.exception_switch{0}", upperLevelExceptionHandlingClause.Offset); } else { writer.WriteLine("br label %.finally_no_error_entry{0}", upperLevelExceptionHandlingClause.Offset); } } if (isFinally) { writer.WriteLine("; End of Finally"); } else { writer.WriteLine("; End of Catch"); } }