12
12
from typing import List , Optional
13
13
14
14
from mypyc .ir .ops import (
15
- BasicBlock , LoadErrorValue , Return , Branch , RegisterOp , ERR_NEVER , ERR_MAGIC ,
16
- ERR_FALSE , ERR_NEG_INT , NO_TRACEBACK_LINE_NO ,
15
+ BasicBlock , LoadErrorValue , Return , Branch , RegisterOp , LoadInt , ERR_NEVER , ERR_MAGIC ,
16
+ ERR_FALSE , ERR_NEG_INT , ERR_ALWAYS , NO_TRACEBACK_LINE_NO , Environment
17
17
)
18
18
from mypyc .ir .func_ir import FuncIR
19
+ from mypyc .ir .rtypes import bool_rprimitive
19
20
20
21
21
22
def insert_exception_handling (ir : FuncIR ) -> None :
@@ -29,7 +30,7 @@ def insert_exception_handling(ir: FuncIR) -> None:
29
30
error_label = add_handler_block (ir )
30
31
break
31
32
if error_label :
32
- ir .blocks = split_blocks_at_errors (ir .blocks , error_label , ir .traceback_name )
33
+ ir .blocks = split_blocks_at_errors (ir .blocks , error_label , ir .traceback_name , ir . env )
33
34
34
35
35
36
def add_handler_block (ir : FuncIR ) -> BasicBlock :
@@ -44,7 +45,8 @@ def add_handler_block(ir: FuncIR) -> BasicBlock:
44
45
45
46
def split_blocks_at_errors (blocks : List [BasicBlock ],
46
47
default_error_handler : BasicBlock ,
47
- func_name : Optional [str ]) -> List [BasicBlock ]:
48
+ func_name : Optional [str ],
49
+ env : Environment ) -> List [BasicBlock ]:
48
50
new_blocks = [] # type: List[BasicBlock]
49
51
50
52
# First split blocks on ops that may raise.
@@ -60,6 +62,7 @@ def split_blocks_at_errors(blocks: List[BasicBlock],
60
62
block .error_handler = None
61
63
62
64
for op in ops :
65
+ target = op
63
66
cur_block .ops .append (op )
64
67
if isinstance (op , RegisterOp ) and op .error_kind != ERR_NEVER :
65
68
# Split
@@ -77,14 +80,24 @@ def split_blocks_at_errors(blocks: List[BasicBlock],
77
80
elif op .error_kind == ERR_NEG_INT :
78
81
variant = Branch .NEG_INT_EXPR
79
82
negated = False
83
+ elif op .error_kind == ERR_ALWAYS :
84
+ variant = Branch .BOOL_EXPR
85
+ negated = True
86
+ # this is a hack to represent the always fail
87
+ # semantics, using a temporary bool with value false
88
+ tmp = LoadInt (0 , rtype = bool_rprimitive )
89
+ cur_block .ops .append (tmp )
90
+ env .add_op (tmp )
91
+ target = tmp
80
92
else :
81
93
assert False , 'unknown error kind %d' % op .error_kind
82
94
83
95
# Void ops can't generate errors since error is always
84
96
# indicated by a special value stored in a register.
85
- assert not op .is_void , "void op generating errors?"
97
+ if op .error_kind != ERR_ALWAYS :
98
+ assert not op .is_void , "void op generating errors?"
86
99
87
- branch = Branch (op ,
100
+ branch = Branch (target ,
88
101
true_label = error_label ,
89
102
false_label = new_block ,
90
103
op = variant ,
0 commit comments