Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,10 @@ extern void _Py_ClearTLBCIndex(_PyThreadStateImpl *tstate);
extern int _Py_ClearUnusedTLBC(PyInterpreterState *interp);
#endif


PyAPI_FUNC(int) _PyCode_Returns(PyCodeObject *);


#ifdef __cplusplus
}
#endif
Expand Down
40 changes: 40 additions & 0 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,46 @@ PyCode_GetFreevars(PyCodeObject *code)
return _PyCode_GetFreevars(code);
}


int
_PyCode_Returns(PyCodeObject *co)
{
// Look up None in co_consts.
Py_ssize_t nconsts = PyTuple_Size(co->co_consts);
int none_index = 0;
for (; none_index < nconsts; none_index++) {
if (PyTuple_GET_ITEM(co->co_consts, none_index) == Py_None) {
break;
}
}
if (none_index == nconsts) {
// None wasn't there, which means there was no implicit return,
// "return", or "return None". That means there must be
// an explicit return (non-None).
return 1;
}

// Walk the bytecode, looking for RETURN_VALUE.
Py_ssize_t len = Py_SIZE(co);
for (int i = 0; i < len; i++) {
_Py_CODEUNIT inst = _Py_GetBaseCodeUnit(co, i);
if (inst.op.code == RETURN_VALUE) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the past we also had RETURN_CONST and we might have something like that in the future, so I think we should make this more robust. Perhaps add a macro in Include/internal/pycore_opcode_utils.h (say IS_RETURN_OPCODE). Also use this new macro in basicblock_returns in flowgraph.c.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

assert(i != 0);
// Ignore it if it returns None.
_Py_CODEUNIT prev = _Py_GetBaseCodeUnit(co, i-1);
if (prev.op.code == LOAD_CONST) {
// We don't worry about EXTENDED_ARG for now.
if (prev.op.arg == none_index) {
continue;
}
}
return 1;
}
}
return 0;
}


#ifdef _Py_TIER2

static void
Expand Down
Loading