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 }); }
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 }); }
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); }