Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        /// <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");
            }
        }
Пример #5
0
        /// <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");
            }
        }