Skip to content

Commit

Permalink
[mypyc] Merge exception ops (#9121)
Browse files Browse the repository at this point in the history
Relates to mypyc/mypyc#734.
  • Loading branch information
TH3CHARLie authored Jul 10, 2020
1 parent f73834e commit a5b7290
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 192 deletions.
4 changes: 2 additions & 2 deletions mypyc/irbuild/for_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ def gen_cleanup(self) -> None:
# an exception was raised during the loop, then err_reg wil be set to
# True. If no_err_occurred_op returns False, then the exception will be
# propagated using the ERR_FALSE flag.
self.builder.primitive_op(no_err_occurred_op, [], self.line)
self.builder.call_c(no_err_occurred_op, [], self.line)


def unsafe_index(
Expand Down Expand Up @@ -539,7 +539,7 @@ def gen_step(self) -> None:

def gen_cleanup(self) -> None:
# Same as for generic ForIterable.
self.builder.primitive_op(no_err_occurred_op, [], self.line)
self.builder.call_c(no_err_occurred_op, [], self.line)


class ForDictionaryKeys(ForDictionaryCommon):
Expand Down
2 changes: 1 addition & 1 deletion mypyc/irbuild/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def add_raise_exception_blocks_to_generator_class(builder: IRBuilder, line: int)
builder.add_bool_branch(comparison, error_block, ok_block)

builder.activate_block(error_block)
builder.primitive_op(raise_exception_with_tb_op, [exc_type, exc_val, exc_tb], line)
builder.call_c(raise_exception_with_tb_op, [exc_type, exc_val, exc_tb], line)
builder.add(Unreachable())
builder.goto_and_activate(ok_block)

Expand Down
6 changes: 3 additions & 3 deletions mypyc/irbuild/nonlocalcontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def gen_return(self, builder: 'IRBuilder', value: Value, line: int) -> None:
# StopIteration instead of using RaiseStandardError because
# the obvious thing doesn't work if the value is a tuple
# (???).
builder.primitive_op(set_stop_iteration_value, [value], NO_TRACEBACK_LINE_NO)
builder.call_c(set_stop_iteration_value, [value], NO_TRACEBACK_LINE_NO)
builder.add(Unreachable())
builder.builder.pop_error_handler()

Expand Down Expand Up @@ -159,7 +159,7 @@ def __init__(self, outer: NonlocalControl, saved: Union[Value, AssignmentTarget]
self.saved = saved

def gen_cleanup(self, builder: 'IRBuilder', line: int) -> None:
builder.primitive_op(restore_exc_info_op, [builder.read(self.saved)], line)
builder.call_c(restore_exc_info_op, [builder.read(self.saved)], line)


class FinallyNonlocalControl(CleanupNonlocalControl):
Expand Down Expand Up @@ -187,5 +187,5 @@ def gen_cleanup(self, builder: 'IRBuilder', line: int) -> None:
target, cleanup = BasicBlock(), BasicBlock()
builder.add(Branch(self.saved, target, cleanup, Branch.IS_ERROR))
builder.activate_block(cleanup)
builder.primitive_op(restore_exc_info_op, [self.saved], line)
builder.call_c(restore_exc_info_op, [self.saved], line)
builder.goto_and_activate(target)
22 changes: 11 additions & 11 deletions mypyc/irbuild/statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def transform_continue_stmt(builder: IRBuilder, node: ContinueStmt) -> None:

def transform_raise_stmt(builder: IRBuilder, s: RaiseStmt) -> None:
if s.expr is None:
builder.primitive_op(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.add(Unreachable())
return

Expand Down Expand Up @@ -278,7 +278,7 @@ def transform_try_except(builder: IRBuilder,
# exception is raised, based on the exception in exc_info.
builder.builder.push_error_handler(double_except_block)
builder.activate_block(except_entry)
old_exc = builder.maybe_spill(builder.primitive_op(error_catch_op, [], line))
old_exc = builder.maybe_spill(builder.call_c(error_catch_op, [], line))
# Compile the except blocks with the nonlocal control flow overridden to clear exc_info
builder.nonlocal_control.append(
ExceptNonlocalControl(builder.nonlocal_control[-1], old_exc))
Expand All @@ -288,7 +288,7 @@ def transform_try_except(builder: IRBuilder,
next_block = None
if type:
next_block, body_block = BasicBlock(), BasicBlock()
matches = builder.primitive_op(
matches = builder.call_c(
exc_matches_op, [builder.accept(type)], type.line
)
builder.add(Branch(matches, body_block, next_block, Branch.BOOL_EXPR))
Expand All @@ -297,7 +297,7 @@ def transform_try_except(builder: IRBuilder,
target = builder.get_assignment_target(var)
builder.assign(
target,
builder.primitive_op(get_exc_value_op, [], var.line),
builder.call_c(get_exc_value_op, [], var.line),
var.line
)
handler_body()
Expand All @@ -307,7 +307,7 @@ def transform_try_except(builder: IRBuilder,

# Reraise the exception if needed
if next_block:
builder.primitive_op(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.add(Unreachable())

builder.nonlocal_control.pop()
Expand All @@ -317,14 +317,14 @@ def transform_try_except(builder: IRBuilder,
# restore the saved exc_info information and continue propagating
# the exception if it exists.
builder.activate_block(cleanup_block)
builder.primitive_op(restore_exc_info_op, [builder.read(old_exc)], line)
builder.call_c(restore_exc_info_op, [builder.read(old_exc)], line)
builder.goto(exit_block)

# Cleanup for if we leave except through a raised exception:
# restore the saved exc_info information and continue propagating
# the exception.
builder.activate_block(double_except_block)
builder.primitive_op(restore_exc_info_op, [builder.read(old_exc)], line)
builder.call_c(restore_exc_info_op, [builder.read(old_exc)], line)
builder.primitive_op(keep_propagating_op, [], NO_TRACEBACK_LINE_NO)
builder.add(Unreachable())

Expand Down Expand Up @@ -402,7 +402,7 @@ def try_finally_entry_blocks(builder: IRBuilder,
builder.add(LoadErrorValue(builder.ret_types[-1]))
)
)
builder.add(Assign(old_exc, builder.primitive_op(error_catch_op, [], -1)))
builder.add(Assign(old_exc, builder.call_c(error_catch_op, [], -1)))
builder.goto(finally_block)

return old_exc
Expand Down Expand Up @@ -442,7 +442,7 @@ def try_finally_resolve_control(builder: IRBuilder,

# Reraise the exception if there was one
builder.activate_block(reraise)
builder.primitive_op(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.add(Unreachable())
builder.builder.pop_error_handler()

Expand Down Expand Up @@ -520,7 +520,7 @@ def transform_try_body() -> None:


def get_sys_exc_info(builder: IRBuilder) -> List[Value]:
exc_info = builder.primitive_op(get_exc_info_op, [], -1)
exc_info = builder.call_c(get_exc_info_op, [], -1)
return [builder.add(TupleGet(exc_info, i, -1)) for i in range(3)]


Expand Down Expand Up @@ -557,7 +557,7 @@ def except_body() -> None:
reraise_block
)
builder.activate_block(reraise_block)
builder.primitive_op(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
builder.add(Unreachable())
builder.activate_block(out_block)

Expand Down
83 changes: 37 additions & 46 deletions mypyc/primitives/exc_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from mypyc.ir.ops import ERR_NEVER, ERR_FALSE, ERR_ALWAYS
from mypyc.ir.rtypes import bool_rprimitive, object_rprimitive, void_rtype, exc_rtuple
from mypyc.primitives.registry import (
simple_emit, call_emit, call_void_emit, call_and_fail_emit, custom_op, c_custom_op
simple_emit, custom_op, c_custom_op
)

# If the argument is a class, raise an instance of the class. Otherwise, assume
Expand All @@ -15,37 +15,33 @@
error_kind=ERR_ALWAYS)

# Raise StopIteration exception with the specified value (which can be NULL).
set_stop_iteration_value = custom_op(
set_stop_iteration_value = c_custom_op(
arg_types=[object_rprimitive],
result_type=bool_rprimitive,
error_kind=ERR_FALSE,
format_str='set_stop_iteration_value({args[0]}); {dest} = 0',
emit=call_and_fail_emit('CPyGen_SetStopIterationValue'))
return_type=void_rtype,
c_function_name='CPyGen_SetStopIterationValue',
error_kind=ERR_ALWAYS)

# Raise exception with traceback.
# Arguments are (exception type, exception value, traceback).
raise_exception_with_tb_op = custom_op(
raise_exception_with_tb_op = c_custom_op(
arg_types=[object_rprimitive, object_rprimitive, object_rprimitive],
result_type=bool_rprimitive,
error_kind=ERR_FALSE,
format_str='raise_exception_with_tb({args[0]}, {args[1]}, {args[2]}); {dest} = 0',
emit=call_and_fail_emit('CPyErr_SetObjectAndTraceback'))
return_type=void_rtype,
c_function_name='CPyErr_SetObjectAndTraceback',
error_kind=ERR_ALWAYS)

# Reraise the currently raised exception.
reraise_exception_op = custom_op(
reraise_exception_op = c_custom_op(
arg_types=[],
result_type=bool_rprimitive,
error_kind=ERR_FALSE,
format_str='reraise_exc; {dest} = 0',
emit=call_and_fail_emit('CPy_Reraise'))
return_type=void_rtype,
c_function_name='CPy_Reraise',
error_kind=ERR_ALWAYS)

# Propagate exception if the CPython error indicator is set (an exception was raised).
no_err_occurred_op = custom_op(
no_err_occurred_op = c_custom_op(
arg_types=[],
result_type=bool_rprimitive,
error_kind=ERR_FALSE,
format_str='{dest} = no_err_occurred',
emit=call_emit('CPy_NoErrOccured'))
return_type=bool_rprimitive,
c_function_name='CPy_NoErrOccured',
error_kind=ERR_FALSE)

# Assert that the error indicator has been set.
assert_err_occured_op = custom_op(
Expand All @@ -68,42 +64,37 @@
# handled exception" (by sticking it into sys.exc_info()). Returns the
# exception that was previously being handled, which must be restored
# later.
error_catch_op = custom_op(
error_catch_op = c_custom_op(
arg_types=[],
result_type=exc_rtuple,
error_kind=ERR_NEVER,
format_str='{dest} = error_catch',
emit=call_emit('CPy_CatchError'))
return_type=exc_rtuple,
c_function_name='CPy_CatchError',
error_kind=ERR_NEVER)

# Restore an old "currently handled exception" returned from.
# error_catch (by sticking it into sys.exc_info())
restore_exc_info_op = custom_op(
restore_exc_info_op = c_custom_op(
arg_types=[exc_rtuple],
result_type=void_rtype,
error_kind=ERR_NEVER,
format_str='restore_exc_info {args[0]}',
emit=call_void_emit('CPy_RestoreExcInfo'))
return_type=void_rtype,
c_function_name='CPy_RestoreExcInfo',
error_kind=ERR_NEVER)

# Checks whether the exception currently being handled matches a particular type.
exc_matches_op = custom_op(
exc_matches_op = c_custom_op(
arg_types=[object_rprimitive],
result_type=bool_rprimitive,
error_kind=ERR_NEVER,
format_str='{dest} = exc_matches {args[0]}',
emit=call_emit('CPy_ExceptionMatches'))
return_type=bool_rprimitive,
c_function_name='CPy_ExceptionMatches',
error_kind=ERR_NEVER)

# Get the value of the exception currently being handled.
get_exc_value_op = custom_op(
get_exc_value_op = c_custom_op(
arg_types=[],
result_type=object_rprimitive,
error_kind=ERR_NEVER,
format_str='{dest} = get_exc_value',
emit=call_emit('CPy_GetExcValue'))
return_type=object_rprimitive,
c_function_name='CPy_GetExcValue',
error_kind=ERR_NEVER)

# Get exception info (exception type, exception instance, traceback object).
get_exc_info_op = custom_op(
get_exc_info_op = c_custom_op(
arg_types=[],
result_type=exc_rtuple,
error_kind=ERR_NEVER,
format_str='{dest} = get_exc_info',
emit=call_emit('CPy_GetExcInfo'))
return_type=exc_rtuple,
c_function_name='CPy_GetExcInfo',
error_kind=ERR_NEVER)
55 changes: 29 additions & 26 deletions mypyc/test-data/analysis.test
Original file line number Diff line number Diff line change
Expand Up @@ -568,49 +568,51 @@ def lol(x):
r5 :: bool
r6 :: short_int
r7 :: int
r8, r9 :: bool
r10 :: short_int
r11, r12 :: int
r8 :: bool
r9 :: short_int
r10, r11 :: int
r12 :: bool
L0:
L1:
r0 = CPyTagged_Id(x)
st = r0
goto L10
L2:
r1 = error_catch
r1 = CPy_CatchError()
r2 = builtins :: module
r3 = unicode_1 :: static ('Exception')
r4 = getattr r2, r3
if is_error(r4) goto L8 (error at lol:4) else goto L3
L3:
r5 = exc_matches r4
r5 = CPy_ExceptionMatches(r4)
if r5 goto L4 else goto L5 :: bool
L4:
r6 = 1
r7 = CPyTagged_Negate(r6)
restore_exc_info r1
CPy_RestoreExcInfo(r1)
return r7
L5:
reraise_exc; r8 = 0
if not r8 goto L8 else goto L6 :: bool
CPy_Reraise()
r12 = 0
if not r12 goto L8 else goto L6 :: bool
L6:
unreachable
L7:
restore_exc_info r1
CPy_RestoreExcInfo(r1)
goto L10
L8:
restore_exc_info r1
r9 = keep_propagating
if not r9 goto L11 else goto L9 :: bool
CPy_RestoreExcInfo(r1)
r8 = keep_propagating
if not r8 goto L11 else goto L9 :: bool
L9:
unreachable
L10:
r10 = 1
r11 = CPyTagged_Add(st, r10)
return r11
r9 = 1
r10 = CPyTagged_Add(st, r9)
return r10
L11:
r12 = <error> :: int
return r12
r11 = <error> :: int
return r11
(0, 0) {x} {x}
(1, 0) {x} {r0}
(1, 1) {r0} {st}
Expand All @@ -626,18 +628,19 @@ L11:
(4, 1) {r1, r6} {r1, r7}
(4, 2) {r1, r7} {r7}
(4, 3) {r7} {}
(5, 0) {r1} {r1, r8}
(5, 1) {r1, r8} {r1}
(5, 0) {r1} {r1}
(5, 1) {r1} {r1, r12}
(5, 2) {r1, r12} {r1}
(6, 0) {} {}
(7, 0) {r1, st} {st}
(7, 1) {st} {st}
(8, 0) {r1} {}
(8, 1) {} {r9}
(8, 2) {r9} {}
(8, 1) {} {r8}
(8, 2) {r8} {}
(9, 0) {} {}
(10, 0) {st} {r10, st}
(10, 1) {r10, st} {r11}
(10, 2) {r11} {}
(11, 0) {} {r12}
(11, 1) {r12} {}
(10, 0) {st} {r9, st}
(10, 1) {r9, st} {r10}
(10, 2) {r10} {}
(11, 0) {} {r11}
(11, 1) {r11} {}

Loading

0 comments on commit a5b7290

Please sign in to comment.