Skip to content

Commit a80a6cf

Browse files
committed
Fix broken catch leaving in ctors
1 parent f781af3 commit a80a6cf

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Copyright (C) 2013 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2013-2022 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
55
// Created: 2013.08.19
66

@@ -20,6 +20,8 @@ public override ActionResult Execute(ProcessorContext context)
2020
{
2121
var body = constructor.Body;
2222
var il = body.GetILProcessor();
23+
var originalLastRet = body.Instructions.Reverse().First(i => i != null && i.OpCode.Code == Code.Ret);
24+
2325
var leavePlaceholder = il.Create(OpCodes.Nop);
2426

2527
var initializeCall = EmitInitializeCall(context, il);
@@ -36,6 +38,11 @@ public override ActionResult Execute(ProcessorContext context)
3638
var ret = il.Create(OpCodes.Ret);
3739
il.Append(ret);
3840
il.Replace(leavePlaceholder, il.Create(OpCodes.Leave, ret));
41+
if (body.ExceptionHandlers.Count != 0) {
42+
foreach (var eHandler in body.ExceptionHandlers) {
43+
FixCatchLeave(eHandler.HandlerStart, eHandler.HandlerEnd, originalLastRet, initializeCall);
44+
}
45+
}
3946

4047
body.InitLocals = true;
4148
var handler = new ExceptionHandler(ExceptionHandlerType.Catch) {
@@ -61,6 +68,19 @@ private void ReplaceRetWithBr(ILProcessor il, Instruction start, Instruction end
6168
}
6269
}
6370

71+
private void FixCatchLeave(Instruction start, Instruction end, Instruction oldRetTarget, Instruction newTarget)
72+
{
73+
var current = start;
74+
while (current != end) {
75+
var next = current.Next;
76+
var code = current.OpCode.Code;
77+
if ((code == Code.Leave || code == Code.Leave_S) && current.Operand == oldRetTarget) {
78+
current.Operand = newTarget;
79+
}
80+
current = next;
81+
}
82+
}
83+
6484
private Instruction GetStartInstruction(ILProcessor il)
6585
{
6686
var instructions = constructor.Body.Instructions;

0 commit comments

Comments
 (0)