@@ -137,6 +137,8 @@ type builder struct {
137137 currentBlock * ssa.BasicBlock
138138 phis []phiNode
139139 deferPtr llvm.Value
140+ deferFrame llvm.Value
141+ landingpad llvm.BasicBlock
140142 difunc llvm.Metadata
141143 dilocals map [* types.Var ]llvm.Metadata
142144 initInlinedAt llvm.Metadata // fake inlinedAt position
@@ -1038,6 +1040,12 @@ func (b *builder) createFunction() {
10381040 }
10391041 }
10401042
1043+ if b .hasDeferFrame () {
1044+ // Create the landing pad block, where execution continues after a
1045+ // panic.
1046+ b .createLandingPad ()
1047+ }
1048+
10411049 // Resolve phi nodes
10421050 for _ , phi := range b .phis {
10431051 block := phi .ssa .Block ()
@@ -1165,9 +1173,12 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
11651173 b .createMapUpdate (mapType .Key (), m , key , value , instr .Pos ())
11661174 case * ssa.Panic :
11671175 value := b .getValue (instr .X )
1168- b .createRuntimeCall ("_panic" , []llvm.Value {value }, "" )
1176+ b .createRuntimeInvoke ("_panic" , []llvm.Value {value }, "" )
11691177 b .CreateUnreachable ()
11701178 case * ssa.Return :
1179+ if b .hasDeferFrame () {
1180+ b .createRuntimeCall ("destroyDeferFrame" , []llvm.Value {b .deferFrame }, "" )
1181+ }
11711182 if len (instr .Results ) == 0 {
11721183 b .CreateRetVoid ()
11731184 } else if len (instr .Results ) == 1 {
@@ -1356,7 +1367,13 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
13561367 cplx := argValues [0 ]
13571368 return b .CreateExtractValue (cplx , 0 , "real" ), nil
13581369 case "recover" :
1359- return b .createRuntimeCall ("_recover" , nil , "" ), nil
1370+ useParentFrame := uint64 (0 )
1371+ if b .hasDeferFrame () {
1372+ // recover() should return the panic value of the parent function,
1373+ // not of the current function.
1374+ useParentFrame = 1
1375+ }
1376+ return b .createRuntimeCall ("_recover" , []llvm.Value {llvm .ConstInt (b .ctx .Int1Type (), useParentFrame , false )}, "" ), nil
13601377 case "ssa:wrapnilchk" :
13611378 // TODO: do an actual nil check?
13621379 return argValues [0 ], nil
@@ -1443,6 +1460,12 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
14431460 return b .createVolatileLoad (instr )
14441461 case strings .HasPrefix (name , "runtime/volatile.Store" ):
14451462 return b .createVolatileStore (instr )
1463+ case name == "runtime.supportsRecover" :
1464+ supportsRecover := uint64 (0 )
1465+ if b .supportsRecover () {
1466+ supportsRecover = 1
1467+ }
1468+ return llvm .ConstInt (b .ctx .Int1Type (), supportsRecover , false ), nil
14461469 case strings .HasPrefix (name , "sync/atomic." ):
14471470 val , ok := b .createAtomicOp (instr )
14481471 if ok {
@@ -1505,7 +1528,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
15051528 params = append (params , context )
15061529 }
15071530
1508- return b .createCall (callee , params , "" ), nil
1531+ return b .createInvoke (callee , params , "" ), nil
15091532}
15101533
15111534// getValue returns the LLVM value of a constant, function value, global, or
0 commit comments