@@ -1765,12 +1765,36 @@ func (p *context) deferStackOwner(fn *ssa.Function) llssa.Function {
17651765 return owner
17661766}
17671767
1768- func (p * context ) emitDo (b llssa.Builder , act llssa.DoAction , ds * explicitDeferStack , fn llssa.Expr , buildCall func (llssa.Builder , llssa.Expr , ... llssa.Expr ) llssa.Expr , args ... llssa.Expr ) llssa.Expr {
1768+ func (p * context ) emitDo (b llssa.Builder , act llssa.DoAction , ds * explicitDeferStack , mayRecover bool , fn llssa.Expr , buildCall func (llssa.Builder , llssa.Expr , ... llssa.Expr ) llssa.Expr , args ... llssa.Expr ) llssa.Expr {
17691769 if ds != nil {
1770- b .DeferTo (ds .owner , ds .stack , fn , buildCall , args ... )
1770+ b .DeferToRecover (ds .owner , ds .stack , mayRecover , fn , buildCall , args ... )
17711771 return llssa .Nil
17721772 }
1773- return b .Do (act , fn , buildCall , args ... )
1773+ switch act {
1774+ case llssa .Call , llssa .Go :
1775+ return b .Do (act , fn , buildCall , args ... )
1776+ default :
1777+ b .DeferRecover (act , mayRecover , fn , buildCall , args ... )
1778+ return llssa .Nil
1779+ }
1780+ }
1781+
1782+ func (p * context ) callMayRecover (v ssa.Value ) bool {
1783+ switch v := v .(type ) {
1784+ case * ssa.Builtin :
1785+ return false
1786+ case * ssa.Function :
1787+ return functionUsesRecover (v )
1788+ case * ssa.MakeClosure :
1789+ if fn , ok := v .Fn .(* ssa.Function ); ok {
1790+ return functionUsesRecover (fn )
1791+ }
1792+ return true
1793+ case * ssa.Call :
1794+ // The deferred callee is the call result, not the factory function.
1795+ return true
1796+ }
1797+ return true
17741798}
17751799
17761800func (p * context ) staticArrayLenBuiltinArg (b llssa.Builder , arg ssa.Value ) (llssa.Expr , bool ) {
@@ -1925,6 +1949,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm
19251949 p .recordCallerLocationForCall (b , call )
19261950 p .emitPCLineLabel (b , call .Pos ())
19271951 cv := call .Value
1952+ mayRecover := p .callMayRecover (cv )
19281953 if mthd := call .Method ; mthd != nil {
19291954 reflectCheck := p .reflectTypeMethodCheck (call , mthd )
19301955 o := p .compileValue (b , cv )
@@ -1934,7 +1959,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm
19341959 hasVArg = fnHasVArg
19351960 }
19361961 args := p .compileValues (b , call .Args , hasVArg )
1937- ret = p .emitDo (b , act , ds , fn , llssa .Builder .Call , args ... )
1962+ ret = p .emitDo (b , act , ds , true , fn , llssa .Builder .Call , args ... )
19381963 if reflectCheck .Kind & llssa .ReflectTypeMethodByName != 0 && reflectCheck .Name == "" {
19391964 b .MarkReflectTypeMethodByNameExpr (ret , 1 )
19401965 }
@@ -1968,7 +1993,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm
19681993 }
19691994 }
19701995 args := p .compileValues (b , args , kind )
1971- ret = p .emitDo (b , act , ds , llssa .Builtin (fn ), llssa .Builder .Call , args ... )
1996+ ret = p .emitDo (b , act , ds , false , llssa .Builtin (fn ), llssa .Builder .Call , args ... )
19721997 case * ssa.Function :
19731998 aFn , pyFn , ftype := p .compileFunction (cv )
19741999 // TODO(xsw): check ca != llssa.Call
@@ -1977,13 +2002,13 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm
19772002 p .inCFunc = true
19782003 args := p .compileValues (b , args , kind )
19792004 p .inCFunc = false
1980- ret = p .emitDo (b , act , ds , aFn .Expr , llssa .Builder .Call , args ... )
2005+ ret = p .emitDo (b , act , ds , mayRecover , aFn .Expr , llssa .Builder .Call , args ... )
19812006 case goFunc :
19822007 args := p .compileValues (b , args , kind )
1983- ret = p .emitDo (b , act , ds , aFn .Expr , llssa .Builder .Call , args ... )
2008+ ret = p .emitDo (b , act , ds , mayRecover , aFn .Expr , llssa .Builder .Call , args ... )
19842009 case pyFunc :
19852010 args := p .compileValues (b , args , kind )
1986- ret = p .emitDo (b , act , ds , pyFn .Expr , llssa .Builder .Call , args ... )
2011+ ret = p .emitDo (b , act , ds , mayRecover , pyFn .Expr , llssa .Builder .Call , args ... )
19872012 case llgoPyList :
19882013 args := p .compileValues (b , args , fnHasVArg )
19892014 ret = b .PyList (args ... )
@@ -2057,33 +2082,33 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm
20572082 b .Unreachable ()
20582083 case llgoAtomicLoad :
20592084 args := p .compileValues (b , args , kind )
2060- ret = p .emitDo (b , act , ds , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
2085+ ret = p .emitDo (b , act , ds , false , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
20612086 return p .atomicLoad (b , args )
20622087 }, args ... )
20632088 case llgoAtomicStore :
20642089 args := p .compileValues (b , args , kind )
2065- p .emitDo (b , act , ds , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
2090+ p .emitDo (b , act , ds , false , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
20662091 return p .atomicStore (b , args )
20672092 }, args ... )
20682093 case llgoAtomicCmpXchg :
20692094 args := p .compileValues (b , args , kind )
2070- ret = p .emitDo (b , act , ds , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
2095+ ret = p .emitDo (b , act , ds , false , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
20712096 return p .atomicCmpXchg (b , args )
20722097 }, args ... )
20732098 case llgoAtomicCmpXchgOK :
20742099 args := p .compileValues (b , args , kind )
2075- ret = p .emitDo (b , act , ds , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
2100+ ret = p .emitDo (b , act , ds , false , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
20762101 return p .atomicCmpXchgOK (b , args )
20772102 }, args ... )
20782103 case llgoAtomicAddReturnNew :
20792104 args := p .compileValues (b , args , kind )
2080- ret = p .emitDo (b , act , ds , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
2105+ ret = p .emitDo (b , act , ds , false , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
20812106 return b .BinOp (token .ADD , p .atomic (b , llssa .OpAdd , args ), args [1 ])
20822107 }, args ... )
20832108 default :
20842109 if ftype >= llgoAtomicOpBase && ftype <= llgoAtomicOpLast {
20852110 args := p .compileValues (b , args , kind )
2086- ret = p .emitDo (b , act , ds , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
2111+ ret = p .emitDo (b , act , ds , false , llssa .Nil , func (b llssa.Builder , _ llssa.Expr , args ... llssa.Expr ) llssa.Expr {
20872112 return p .atomic (b , llssa .AtomicOp (ftype - llgoAtomicOpBase ), args )
20882113 }, args ... )
20892114 } else {
@@ -2093,7 +2118,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm
20932118 default :
20942119 fn := p .compileValue (b , cv )
20952120 args := p .compileValues (b , args , kind )
2096- ret = p .emitDo (b , act , ds , fn , llssa .Builder .Call , args ... )
2121+ ret = p .emitDo (b , act , ds , mayRecover , fn , llssa .Builder .Call , args ... )
20972122 }
20982123 return
20992124}
0 commit comments