Skip to content

Commit 6589315

Browse files
committed
W27c python#1: emitSetupWithCommon → C body + bridge stub
Helper for emitSetupWith + emitBeforeWith. Per W27c Step A scope. C body: hir_builder_emit_setup_with_common_c (~45 lines). Pops manager, allocates enter+exit, emits load_attr_special_reg for both, pushes exit, allocates enter_result, emits vectorcall_reg with CallFlags::None=0u, sets enter as operand 0, sets frame state, emits. PY_VERSION_HEX conditional (_Py_Identifier vs PyObject*) folded into C++ stub: ids are passed as opaque void* downward. is_async drives error message text selection. NEW BRIDGE: hir_builder_emit_setup_with_common_c — out-param returns enter_result via void**. C primitives used: hir_c_create_load_attr_special_reg + hir_c_create_vectorcall_reg + hir_c_set_operand + hir_deopt_set_frame_state + hir_builder_temps_alloc_stack (all existing). C++ HIRBuilder::emitSetupWithCommon → 6-line bridge stub returning Register* via cast of out-param. Verification: cmake --build target jit/phoenix_jit clean (BUILD_EXIT=0). This is the chain-dep root for W27c python#2 (SetupWith) + python#3 (BeforeWith).
1 parent 6e24cff commit 6589315

2 files changed

Lines changed: 52 additions & 32 deletions

File tree

Python/jit/hir/builder.cpp

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4531,6 +4531,10 @@ void HIRBuilder::emitGetANext(TranslationContext& tc) {
45314531
static_cast<void*>(&tc), static_cast<void*>(current_func_));
45324532
}
45334533

4534+
extern "C" void hir_builder_emit_setup_with_common_c(
4535+
void *tc, void *builder, void *enter_id, void *exit_id,
4536+
int is_async, void **out_enter_result);
4537+
45344538
Register* HIRBuilder::emitSetupWithCommon(
45354539
TranslationContext& tc,
45364540
#if PY_VERSION_HEX < 0x030C0000
@@ -4541,38 +4545,11 @@ Register* HIRBuilder::emitSetupWithCommon(
45414545
PyObject* exit_id,
45424546
#endif
45434547
bool is_async) {
4544-
// Load the enter and exit attributes from the manager, push exit, and return
4545-
// the result of calling enter().
4546-
PhxPtrArray& stack = tc.frame.stack;
4547-
Register* manager = static_cast<Register*>(phx_ptr_arr_pop(&stack));
4548-
Register* enter = temps_.AllocateStack();
4549-
Register* exit = temps_.AllocateStack();
4550-
tc.emitLoadAttrSpecial(
4551-
enter,
4552-
manager,
4553-
enter_id,
4554-
is_async
4555-
? "'%.200s' object does not support the asynchronous context manager "
4556-
"protocol"
4557-
: "'%.200s' object does not support the context manager protocol",
4558-
tc.frame);
4559-
tc.emitLoadAttrSpecial(
4560-
exit,
4561-
manager,
4562-
exit_id,
4563-
is_async
4564-
? "'%.200s' object does not support the asynchronous context manager "
4565-
"protocol (missed __aexit__ method)"
4566-
: "'%.200s' object does not support the context manager protocol "
4567-
"(missed __exit__ method)",
4568-
tc.frame);
4569-
phx_ptr_arr_push(&stack, exit);
4570-
4571-
Register* enter_result = temps_.AllocateStack();
4572-
auto call = tc.emitVectorCall(1, enter_result, CallFlags::None);
4573-
call->setFrameState(tc.frame);
4574-
call->SetOperand(0, enter);
4575-
return enter_result;
4548+
void *enter_result = nullptr;
4549+
hir_builder_emit_setup_with_common_c(
4550+
&tc, this, (void*)enter_id, (void*)exit_id, is_async ? 1 : 0,
4551+
&enter_result);
4552+
return static_cast<Register*>(enter_result);
45764553
}
45774554

45784555
void HIRBuilder::emitBeforeWith(

Python/jit/hir/builder_emit_c.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4084,4 +4084,47 @@ void hir_builder_emit_primitive_load_const_c(
40844084
(void)func; /* unused; tc owns the emission */
40854085
}
40864086

4087+
/* W27c #1: emitSetupWithCommon — helper for emitSetupWith + emitBeforeWith.
4088+
* Mirrors C++ HIRBuilder::emitSetupWithCommon @ builder.cpp:4534.
4089+
*
4090+
* Loads __enter__ + __exit__ via emitLoadAttrSpecial, pushes exit, emits
4091+
* VectorCall(enter), returns enter_result via out-param. PY_VERSION_HEX
4092+
* conditional (_Py_Identifier vs PyObject*) folded in C++ stub: ids are
4093+
* passed as opaque void*. is_async selects the error message text. */
4094+
void hir_builder_emit_setup_with_common_c(
4095+
PhxTranslationContext *tc,
4096+
void *builder,
4097+
void *enter_id,
4098+
void *exit_id,
4099+
int is_async,
4100+
void **out_enter_result) {
4101+
void *manager = phx_ptr_arr_pop(&tc->frame.stack);
4102+
void *enter = hir_builder_temps_alloc_stack(builder);
4103+
void *exit = hir_builder_temps_alloc_stack(builder);
4104+
4105+
const char *enter_fmt = is_async
4106+
? "'%.200s' object does not support the asynchronous context manager "
4107+
"protocol"
4108+
: "'%.200s' object does not support the context manager protocol";
4109+
const char *exit_fmt = is_async
4110+
? "'%.200s' object does not support the asynchronous context manager "
4111+
"protocol (missed __aexit__ method)"
4112+
: "'%.200s' object does not support the context manager protocol "
4113+
"(missed __exit__ method)";
4114+
phx_tc_emit(tc, hir_c_create_load_attr_special_reg(
4115+
enter, manager, enter_id, enter_fmt, &tc->frame));
4116+
phx_tc_emit(tc, hir_c_create_load_attr_special_reg(
4117+
exit, manager, exit_id, exit_fmt, &tc->frame));
4118+
phx_ptr_arr_push(&tc->frame.stack, exit);
4119+
4120+
void *enter_result = hir_builder_temps_alloc_stack(builder);
4121+
/* CallFlags::None = 0. VectorCall(1, enter_result, None) + setFrameState. */
4122+
void *call = hir_c_create_vectorcall_reg(1, enter_result, 0u);
4123+
hir_deopt_set_frame_state(call, &tc->frame);
4124+
hir_c_set_operand(call, 0, enter);
4125+
phx_tc_emit(tc, call);
4126+
4127+
*out_enter_result = enter_result;
4128+
}
4129+
40874130

0 commit comments

Comments
 (0)