예제 #1
0
 public override void ExceptionHandlerSetup(PlaceholderRef site)
 {
     inExceptHandler++;
     region.Write(new byte[] {
         0x31, 0xc9,                    // xor ecx, ecx
         0x51                           // push ecx
     });
     region.Write(new byte[] { 0x68 }); // push imm32
     region.WritePlaceholderRef(site);
     region.Write(new byte[] {
         0x51,             // push ecx
         0xff, 0x75, 0x00, // push [ebp]
         0x89, 0x65, 0x00  // mov [ebp], esp
     });
 }
예제 #2
0
 public override void ExceptionHandlerSetup(PlaceholderRef site)
 {
     region.Write(new byte[] {
         0x48, 0x31, 0xc9,                    // xor rcx, rcx
         0x51                                 // push rcx
     });
     region.Write(new byte[] { 0x48, 0xb9 }); // mov rcx, imm64
     region.WritePlaceholderRef(site);
     region.Write(new byte[] {
         0x51,                  // push rcx
         0x48, 0x31, 0xc9,      // xor rcx, rcx
         0x51,                  // push rcx
         0xff, 0x75, 0x00,      // push [rbp]
         0x48, 0x89, 0x65, 0x00 // mov [rbp], rsp
     });
 }
예제 #3
0
        public override void Generate(Generator generator, TypeReference returnType)
        {
            base.Generate(generator, returnType);
            //
            generator.Symbols.Source(generator.Assembler.Region.CurrentLocation, this);
            PlaceholderRef fonCatchJump = null;

            if (finallyStatement != null)
            {
                fonCatchJump = new PlaceholderRef();
                generator.Assembler.ExceptionHandlerSetup(fonCatchJump);
                generator.Resolver.EnterContext();
                generator.Resolver.RegisterTryContext();
            }
            PlaceholderRef onCatchJump = null;

            if (catches.Count > 0)
            {
                onCatchJump = new PlaceholderRef();
                generator.Assembler.ExceptionHandlerSetup(onCatchJump);
            }
            generator.Resolver.EnterContext();
            generator.Resolver.RegisterTryContext();
            statement.Generate(generator, returnType);
            returns = statement.Returns();
            Resolver.Context statementContext = generator.Resolver.LeaveContextAcquire();
            if (catches.Count > 0)
            {
                generator.Assembler.ExceptionHandlerRemove();
                JumpToken noExceptionJump = generator.Assembler.CreateJumpToken();
                generator.Assembler.Jump(noExceptionJump);
                generator.Assembler.SetDestination(onCatchJump);

                JumpToken noReturnJump = generator.Assembler.CreateJumpToken();
                generator.Assembler.JumpIfNotMarked(noReturnJump);
                generator.Assembler.UnmarkType();
                ReturnStatement.DoReturn(this, generator);
                generator.Assembler.SetDestination(noReturnJump);

                generator.Assembler.StoreVariable(valueSlot);

                List <JumpToken> escape = new List <JumpToken>();

                foreach (Catch c in catches)
                {
                    generator.Symbols.Source(generator.Assembler.Region.CurrentLocation, c);
                    generator.Assembler.RetrieveVariable(valueSlot);
                    JumpToken noMatch = generator.Assembler.CreateJumpToken();
                    generator.Assembler.TypeConversionDynamicNotNull(c.type.Id);
                    generator.Assembler.JumpIfUnassigned(noMatch);
                    generator.Assembler.StoreVariable(valueSlot);
                    generator.Resolver.EnterContext();
                    generator.Resolver.AddVariable(c.identifier, c.type, valueSlot, true);
                    generator.Resolver.AssignSlot(valueSlot);
                    c.statement.Generate(generator, returnType);
                    returns = returns && c.statement.Returns();
                    generator.Resolver.LeaveContext();
                    JumpToken jt = generator.Assembler.CreateJumpToken();
                    escape.Add(jt);
                    generator.Assembler.Jump(jt);
                    generator.Assembler.SetDestination(noMatch);
                }
                //unhandled, rethrow
                generator.Assembler.RetrieveVariable(valueSlot);
                generator.Assembler.ExceptionHandlerInvoke();
                foreach (JumpToken jt in escape)
                {
                    generator.Assembler.SetDestination(jt);
                }
                generator.Assembler.SetDestination(noExceptionJump);
            }
            if (finallyStatement != null)
            {
                generator.Symbols.Source(generator.Assembler.Region.CurrentLocation, finallyLocation);
                generator.Resolver.LeaveContext();
                generator.Assembler.ExceptionHandlerRemove();
                generator.Assembler.Empty();
                generator.Assembler.SetDestination(fonCatchJump);
                JumpToken fnoReturnJump = generator.Assembler.CreateJumpToken();
                generator.Assembler.JumpIfNotMarked(fnoReturnJump);
                generator.Assembler.UnmarkType();
                generator.Assembler.StoreVariable(returnSlot);
                generator.Assembler.SetDestination(fnoReturnJump);
                generator.Assembler.StoreVariable(valueSlot);
                generator.Resolver.EnterContext();
                finallyStatement.Generate(generator, returnType);
                generator.Resolver.LeaveAndMergeContext();
                if (catches.Count == 0) // if there are no catches we can be sure the whole try part completed and so we can use the variables initialized by it.
                {
                    generator.Resolver.MergeContext(statementContext);
                }

                generator.Assembler.RetrieveVariable(returnSlot);
                JumpToken fonExceptionFinallyJump = generator.Assembler.CreateJumpToken();
                generator.Assembler.JumpIfUnassigned(fonExceptionFinallyJump);
                ReturnStatement.DoReturn(this, generator);
                generator.Assembler.SetDestination(fonExceptionFinallyJump);

                generator.Assembler.RetrieveVariable(valueSlot);
                JumpToken fnoException = generator.Assembler.CreateJumpToken();
                generator.Assembler.JumpIfUnassigned(fnoException);
                generator.Assembler.ExceptionHandlerInvoke();
                generator.Assembler.SetDestination(fnoException);
            }
            generator.Resolver.ReleaseContext(statementContext);
        }