Skip to content

Commit 6d402b1

Browse files
committed
compiler: fix deferred calls may not be executed before optimized exceptional forwarding
1 parent 2170aa2 commit 6d402b1

File tree

5 files changed

+41
-10
lines changed

5 files changed

+41
-10
lines changed

src/julec/obj/cxx/scope.jule

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1783,8 +1783,22 @@ impl scopeCoder {
17831783
}
17841784

17851785
fn exceptionalForwarding(mut &self, mut m: &opt::ExceptionalForwardingExpr) {
1786-
self.oc.write("return ")
1786+
hasDefer := m.Func.Decl != nil && m.Func.Decl.HasDefer
1787+
if !hasDefer {
1788+
self.oc.write("return ")
1789+
self.oc.ec.pureFuncCall(m.Expr)
1790+
ret
1791+
}
1792+
if m.Func.Decl.IsVoid() {
1793+
self.oc.write("__jule_VoidExceptional")
1794+
} else {
1795+
self.oc.write("__jule_Exceptional<")
1796+
self.oc.tc.rc.codeMut1(&self.oc.Buf, m.Func.Result)
1797+
self.oc.write(">")
1798+
}
1799+
self.oc.write(" __result = ")
17871800
self.oc.ec.pureFuncCall(m.Expr)
1801+
self.oc.write("; " + deferStackName + ".call(); return __result;")
17881802
}
17891803

17901804
// Generates C++ code of statement.

src/julec/opt/expr.jule

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -809,12 +809,12 @@ impl exprOptimizer {
809809
// Tries to optimize scope.
810810
// If the |child| true and |self.scopeOpt| is not nil, calls the optimizeChildHard().
811811
// Otherwise optimizes the scope with immutable copy of the data if exist.
812-
fn scope(*self, mut s: &sema::Scope, child: bool) {
812+
fn scope(*self, mut owner: &sema::FuncIns, mut s: &sema::Scope, child: bool) {
813813
if child && self.scopeOpt != nil {
814814
self.scopeOpt.optimizeChildHard(s)
815815
ret
816816
}
817-
mut scopt := scopeOptimizer.new(s)
817+
mut scopt := scopeOptimizer.new(owner, s)
818818
if self.data != nil {
819819
// If data exist, use it as immutable copy.
820820
// Because this scope is not child.
@@ -932,7 +932,7 @@ impl exprOptimizer {
932932
// Handle exceptional handler scope as child.
933933
// Because it is actually a child scope.
934934
const Child = true
935-
self.scope(m.Except, Child)
935+
self.scope(nil, m.Except, Child)
936936
}
937937
match {
938938
| StdStrings && meta::Program.StrBuilder != nil:
@@ -994,7 +994,7 @@ impl exprOptimizer {
994994
// It is possible with references, but it is unsafe operation.
995995
// So optimizer is not have to thing such cases.
996996
const Child = false
997-
self.scope(m.Func.Scope, Child)
997+
self.scope(m.Func, m.Func.Scope, Child)
998998
}
999999

10001000
fn inspectStep(*self, mut &m: *sema::Expr) {

src/julec/opt/model.jule

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct BytesFromStr {
1515
}
1616

1717
struct ExceptionalForwardingExpr {
18+
Func: &sema::FuncIns
1819
Expr: &sema::FuncCallExpr
1920
}
2021

src/julec/opt/optimizer.jule

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl Optimizer {
3939
ret
4040
}
4141
for (_, mut ins) in func.Instances {
42-
mut so := scopeOptimizer.new(ins.Scope)
42+
mut so := scopeOptimizer.new(ins, ins.Scope)
4343
so.optimize()
4444
}
4545
}

src/julec/opt/scope.jule

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ use "std/strings"
1515

1616
// Scope optimizer that applies target-independent optimizations.
1717
struct scopeOptimizer {
18+
owner: &sema::FuncIns
1819
parent: &scopeOptimizer
1920
i: int
2021
scope: &sema::Scope
2122
data: &data // Should be non-nil guaranteed.
2223
}
2324

2425
impl scopeOptimizer {
25-
fn new(mut scope: &sema::Scope): &scopeOptimizer {
26+
fn new(mut owner: &sema::FuncIns, mut scope: &sema::Scope): &scopeOptimizer {
2627
mut sc := &scopeOptimizer{
28+
owner: owner,
2729
scope: scope,
2830
data: &data{
2931
boundary: new(boundary),
@@ -34,6 +36,16 @@ impl scopeOptimizer {
3436
ret sc
3537
}
3638

39+
fn getOwner(mut &self): &sema::FuncIns {
40+
mut s := self
41+
for s != nil; s = s.parent {
42+
if s.owner != nil {
43+
ret s.owner
44+
}
45+
}
46+
ret nil
47+
}
48+
3749
fn setCurrentStmt(mut &self, mut stmt: any) {
3850
self.scope.Stmts[self.i] = unsafe { *(*sema::Stmt)(&stmt) }
3951
}
@@ -925,7 +937,11 @@ impl scopeOptimizer {
925937
!obj::IsForwarded(fc.Except) {
926938
ret
927939
}
928-
self.setCurrentStmt(&ExceptionalForwardingExpr{Expr: fc})
940+
mut owner := self.getOwner()
941+
if owner == nil {
942+
panic("unreachable")
943+
}
944+
self.setCurrentStmt(&ExceptionalForwardingExpr{Func: owner, Expr: fc})
929945
}
930946

931947
// Like optimizeStmt, but handles independent statement from the scope.
@@ -946,7 +962,7 @@ impl scopeOptimizer {
946962
// `x = 10; y = 20`, after optimization.
947963
mut scope := new(sema::Scope)
948964
scope.Stmts = append(scope.Stmts, *stmt)
949-
mut opt := scopeOptimizer.new(scope)
965+
mut opt := scopeOptimizer.new(nil, scope)
950966
opt.optimize()
951967
*stmt = scope
952968
}
@@ -988,7 +1004,7 @@ impl scopeOptimizer {
9881004

9891005
// Optimizes child scope using mutable data.
9901006
fn optimizeChild(mut &self, mut child: &sema::Scope) {
991-
mut so := scopeOptimizer.new(child)
1007+
mut so := scopeOptimizer.new(nil, child)
9921008
so.parent = self
9931009
so.data = self.data
9941010
so.optimize()

0 commit comments

Comments
 (0)