85
85
(opcode) == SETUP_WITH || \
86
86
(opcode) == SETUP_CLEANUP)
87
87
88
+ #define HAS_TARGET (opcode ) \
89
+ (IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode))
90
+
88
91
/* opcodes that must be last in the basicblock */
89
92
#define IS_TERMINATOR_OPCODE (opcode ) \
90
93
(IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode))
@@ -141,33 +144,31 @@ static struct location NO_LOCATION = {-1, -1, -1, -1};
141
144
142
145
typedef struct jump_target_label_ {
143
146
int id ;
144
- struct basicblock_ * block ;
145
147
} jump_target_label ;
146
148
147
- static struct jump_target_label_ NO_LABEL = {-1 , NULL };
149
+ static struct jump_target_label_ NO_LABEL = {-1 };
148
150
149
151
#define SAME_LABEL (L1 , L2 ) ((L1).id == (L2).id)
150
152
#define IS_LABEL (L ) (!SAME_LABEL((L), (NO_LABEL)))
151
153
152
154
#define NEW_JUMP_TARGET_LABEL (C , NAME ) \
153
- jump_target_label NAME = {cfg_new_label_id (CFG_BUILDER(C)), cfg_builder_new_block(CFG_BUILDER(C))} ; \
155
+ jump_target_label NAME = cfg_new_label (CFG_BUILDER(C)); \
154
156
if (!IS_LABEL(NAME)) { \
155
157
return 0; \
156
158
}
157
159
158
- #define USE_LABEL (C , LBL ) cfg_builder_use_label(CFG_BUILDER(C), LBL)
160
+ #define USE_LABEL (C , LBL ) \
161
+ if (cfg_builder_use_label(CFG_BUILDER(C), LBL) < 0) { \
162
+ return 0; \
163
+ }
159
164
160
165
struct instr {
161
166
int i_opcode ;
162
167
int i_oparg ;
163
- /* target block (if jump instruction) -- we temporarily have both the label
164
- and the block in the instr. The label is set by front end, and the block
165
- is calculated by backend. */
166
- jump_target_label i_target_label ;
167
- struct basicblock_ * i_target ;
168
- /* target block when exception is raised, should not be set by front-end. */
169
- struct basicblock_ * i_except ;
170
168
struct location i_loc ;
169
+ /* The following fields should not be set by the front-end: */
170
+ struct basicblock_ * i_target ; /* target block (if jump instruction) */
171
+ struct basicblock_ * i_except ; /* target block when exception is raised */
171
172
};
172
173
173
174
typedef struct exceptstack {
@@ -351,12 +352,12 @@ enum {
351
352
typedef struct cfg_builder_ {
352
353
/* The entryblock, at which control flow begins. All blocks of the
353
354
CFG are reachable through the b_next links */
354
- basicblock * cfg_entryblock ;
355
+ basicblock * g_entryblock ;
355
356
/* Pointer to the most recently allocated block. By following
356
357
b_list links, you can reach all allocated blocks. */
357
- basicblock * block_list ;
358
+ basicblock * g_block_list ;
358
359
/* pointer to the block currently being constructed */
359
- basicblock * curblock ;
360
+ basicblock * g_curblock ;
360
361
/* label for the next instruction to be placed */
361
362
jump_target_label g_current_label ;
362
363
/* next free label id */
@@ -752,7 +753,7 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset)
752
753
static void
753
754
cfg_builder_check (cfg_builder * g )
754
755
{
755
- for (basicblock * block = g -> block_list ; block != NULL ; block = block -> b_list ) {
756
+ for (basicblock * block = g -> g_block_list ; block != NULL ; block = block -> b_list ) {
756
757
assert (!_PyMem_IsPtrFreed (block ));
757
758
if (block -> b_instr != NULL ) {
758
759
assert (block -> b_ialloc > 0 );
@@ -770,7 +771,7 @@ static void
770
771
cfg_builder_free (cfg_builder * g )
771
772
{
772
773
cfg_builder_check (g );
773
- basicblock * b = g -> block_list ;
774
+ basicblock * b = g -> g_block_list ;
774
775
while (b != NULL ) {
775
776
if (b -> b_instr ) {
776
777
PyObject_Free ((void * )b -> b_instr );
@@ -867,10 +868,11 @@ compiler_set_qualname(struct compiler *c)
867
868
return 1 ;
868
869
}
869
870
870
- static int
871
- cfg_new_label_id (cfg_builder * g )
871
+ static jump_target_label
872
+ cfg_new_label (cfg_builder * g )
872
873
{
873
- return g -> g_next_free_label ++ ;
874
+ jump_target_label lbl = {g -> g_next_free_label ++ };
875
+ return lbl ;
874
876
}
875
877
876
878
/* Allocate a new block and return a pointer to it.
@@ -885,8 +887,8 @@ cfg_builder_new_block(cfg_builder *g)
885
887
return NULL ;
886
888
}
887
889
/* Extend the singly linked list of blocks with new block. */
888
- b -> b_list = g -> block_list ;
889
- g -> block_list = b ;
890
+ b -> b_list = g -> g_block_list ;
891
+ g -> g_block_list = b ;
890
892
b -> b_label = -1 ;
891
893
return b ;
892
894
}
@@ -895,8 +897,8 @@ static basicblock *
895
897
cfg_builder_use_next_block (cfg_builder * g , basicblock * block )
896
898
{
897
899
assert (block != NULL );
898
- g -> curblock -> b_next = block ;
899
- g -> curblock = block ;
900
+ g -> g_curblock -> b_next = block ;
901
+ g -> g_curblock = block ;
900
902
return block ;
901
903
}
902
904
@@ -1282,17 +1284,12 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
1282
1284
*/
1283
1285
1284
1286
static int
1285
- basicblock_addop (basicblock * b , int opcode , int oparg ,
1286
- jump_target_label target , struct location loc )
1287
+ basicblock_addop (basicblock * b , int opcode , int oparg , struct location loc )
1287
1288
{
1288
1289
assert (IS_WITHIN_OPCODE_RANGE (opcode ));
1289
1290
assert (!IS_ASSEMBLER_OPCODE (opcode ));
1290
- assert (HAS_ARG (opcode ) || oparg == 0 );
1291
+ assert (HAS_ARG (opcode ) || HAS_TARGET ( opcode ) || oparg == 0 );
1291
1292
assert (0 <= oparg && oparg < (1 << 30 ));
1292
- assert (!IS_LABEL (target ) ||
1293
- IS_JUMP_OPCODE (opcode ) ||
1294
- IS_BLOCK_PUSH_OPCODE (opcode ));
1295
- assert (oparg == 0 || !IS_LABEL (target ));
1296
1293
1297
1294
int off = basicblock_next_instr (b );
1298
1295
if (off < 0 ) {
@@ -1301,7 +1298,6 @@ basicblock_addop(basicblock *b, int opcode, int oparg,
1301
1298
struct instr * i = & b -> b_instr [off ];
1302
1299
i -> i_opcode = opcode ;
1303
1300
i -> i_oparg = oparg ;
1304
- i -> i_target_label = target ;
1305
1301
i -> i_target = NULL ;
1306
1302
i -> i_loc = loc ;
1307
1303
@@ -1314,46 +1310,39 @@ cfg_builder_current_block_is_terminated(cfg_builder *g)
1314
1310
if (IS_LABEL (g -> g_current_label )) {
1315
1311
return true;
1316
1312
}
1317
- struct instr * last = basicblock_last_instr (g -> curblock );
1313
+ struct instr * last = basicblock_last_instr (g -> g_curblock );
1318
1314
return last && IS_TERMINATOR_OPCODE (last -> i_opcode );
1319
1315
}
1320
1316
1321
1317
static int
1322
1318
cfg_builder_maybe_start_new_block (cfg_builder * g )
1323
1319
{
1324
1320
if (cfg_builder_current_block_is_terminated (g )) {
1325
- basicblock * b ;
1326
- if (IS_LABEL (g -> g_current_label )) {
1327
- b = g -> g_current_label .block ;
1328
- b -> b_label = g -> g_current_label .id ;
1329
- g -> g_current_label = NO_LABEL ;
1330
- }
1331
- else {
1332
- b = cfg_builder_new_block (g );
1333
- }
1321
+ basicblock * b = cfg_builder_new_block (g );
1334
1322
if (b == NULL ) {
1335
1323
return -1 ;
1336
1324
}
1325
+ b -> b_label = g -> g_current_label .id ;
1326
+ g -> g_current_label = NO_LABEL ;
1337
1327
cfg_builder_use_next_block (g , b );
1338
1328
}
1339
1329
return 0 ;
1340
1330
}
1341
1331
1342
1332
static int
1343
- cfg_builder_addop (cfg_builder * g , int opcode , int oparg , jump_target_label target ,
1344
- struct location loc )
1333
+ cfg_builder_addop (cfg_builder * g , int opcode , int oparg , struct location loc )
1345
1334
{
1346
1335
if (cfg_builder_maybe_start_new_block (g ) != 0 ) {
1347
1336
return -1 ;
1348
1337
}
1349
- return basicblock_addop (g -> curblock , opcode , oparg , target , loc );
1338
+ return basicblock_addop (g -> g_curblock , opcode , oparg , loc );
1350
1339
}
1351
1340
1352
1341
static int
1353
1342
cfg_builder_addop_noarg (cfg_builder * g , int opcode , struct location loc )
1354
1343
{
1355
1344
assert (!HAS_ARG (opcode ));
1356
- return cfg_builder_addop (g , opcode , 0 , NO_LABEL , loc );
1345
+ return cfg_builder_addop (g , opcode , 0 , loc );
1357
1346
}
1358
1347
1359
1348
static Py_ssize_t
@@ -1565,15 +1554,15 @@ cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct locatio
1565
1554
EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */
1566
1555
1567
1556
int oparg_ = Py_SAFE_DOWNCAST (oparg , Py_ssize_t , int );
1568
- return cfg_builder_addop (g , opcode , oparg_ , NO_LABEL , loc );
1557
+ return cfg_builder_addop (g , opcode , oparg_ , loc );
1569
1558
}
1570
1559
1571
1560
static int
1572
1561
cfg_builder_addop_j (cfg_builder * g , int opcode , jump_target_label target , struct location loc )
1573
1562
{
1574
1563
assert (IS_LABEL (target ));
1575
1564
assert (IS_JUMP_OPCODE (opcode ) || IS_BLOCK_PUSH_OPCODE (opcode ));
1576
- return cfg_builder_addop (g , opcode , 0 , target , loc );
1565
+ return cfg_builder_addop (g , opcode , target . id , loc );
1577
1566
}
1578
1567
1579
1568
@@ -1795,11 +1784,11 @@ compiler_enter_scope(struct compiler *c, identifier name,
1795
1784
c -> c_nestlevel ++ ;
1796
1785
1797
1786
cfg_builder * g = CFG_BUILDER (c );
1798
- g -> block_list = NULL ;
1787
+ g -> g_block_list = NULL ;
1799
1788
block = cfg_builder_new_block (g );
1800
1789
if (block == NULL )
1801
1790
return 0 ;
1802
- g -> curblock = g -> cfg_entryblock = block ;
1791
+ g -> g_curblock = g -> g_entryblock = block ;
1803
1792
g -> g_current_label = NO_LABEL ;
1804
1793
1805
1794
if (u -> u_scope_type == COMPILER_SCOPE_MODULE ) {
@@ -7092,7 +7081,7 @@ stackdepth(basicblock *entryblock, int code_flags)
7092
7081
maxdepth = new_depth ;
7093
7082
}
7094
7083
assert (depth >= 0 ); /* invalid code or bug in stackdepth() */
7095
- if (is_jump (instr ) || is_block_push ( instr )) {
7084
+ if (HAS_TARGET (instr -> i_opcode )) {
7096
7085
effect = stack_effect (instr -> i_opcode , instr -> i_oparg , 1 );
7097
7086
assert (effect != PY_INVALID_STACK_EFFECT );
7098
7087
int target_depth = depth + effect ;
@@ -7393,7 +7382,7 @@ mark_cold(basicblock *entryblock) {
7393
7382
7394
7383
static int
7395
7384
push_cold_blocks_to_end (cfg_builder * g , int code_flags ) {
7396
- basicblock * entryblock = g -> cfg_entryblock ;
7385
+ basicblock * entryblock = g -> g_entryblock ;
7397
7386
if (entryblock -> b_next == NULL ) {
7398
7387
/* single basicblock, no need to reorder */
7399
7388
return 0 ;
@@ -7410,17 +7399,14 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
7410
7399
if (explicit_jump == NULL ) {
7411
7400
return -1 ;
7412
7401
}
7413
- jump_target_label next_label = {b -> b_next -> b_label , b -> b_next };
7414
- basicblock_addop (explicit_jump , JUMP , 0 , next_label , NO_LOCATION );
7402
+ basicblock_addop (explicit_jump , JUMP , b -> b_next -> b_label , NO_LOCATION );
7415
7403
explicit_jump -> b_cold = 1 ;
7416
7404
explicit_jump -> b_next = b -> b_next ;
7417
7405
b -> b_next = explicit_jump ;
7418
7406
7419
- /* calculate target from target_label */
7420
- /* TODO: formalize an API for adding jumps in the backend */
7407
+ /* set target */
7421
7408
struct instr * last = basicblock_last_instr (explicit_jump );
7422
- last -> i_target = last -> i_target_label .block ;
7423
- last -> i_target_label = NO_LABEL ;
7409
+ last -> i_target = explicit_jump -> b_next ;
7424
7410
}
7425
7411
}
7426
7412
@@ -8226,12 +8212,9 @@ dump_instr(struct instr *i)
8226
8212
if (HAS_ARG (i -> i_opcode )) {
8227
8213
sprintf (arg , "arg: %d " , i -> i_oparg );
8228
8214
}
8229
- if (is_jump ( i )) {
8215
+ if (HAS_TARGET ( i -> i_opcode )) {
8230
8216
sprintf (arg , "target: %p " , i -> i_target );
8231
8217
}
8232
- if (is_block_push (i )) {
8233
- sprintf (arg , "except_target: %p " , i -> i_target );
8234
- }
8235
8218
fprintf (stderr , "line: %d, opcode: %d %s%s%s\n" ,
8236
8219
i -> i_loc .lineno , i -> i_opcode , arg , jabs , jrel );
8237
8220
}
@@ -8524,7 +8507,7 @@ assemble(struct compiler *c, int addNone)
8524
8507
}
8525
8508
8526
8509
/* Make sure every block that falls off the end returns None. */
8527
- if (!basicblock_returns (CFG_BUILDER (c )-> curblock )) {
8510
+ if (!basicblock_returns (CFG_BUILDER (c )-> g_curblock )) {
8528
8511
UNSET_LOC (c );
8529
8512
if (addNone )
8530
8513
ADDOP_LOAD_CONST (c , Py_None );
@@ -8546,7 +8529,7 @@ assemble(struct compiler *c, int addNone)
8546
8529
}
8547
8530
8548
8531
int nblocks = 0 ;
8549
- for (basicblock * b = CFG_BUILDER (c )-> block_list ; b != NULL ; b = b -> b_list ) {
8532
+ for (basicblock * b = CFG_BUILDER (c )-> g_block_list ; b != NULL ; b = b -> b_list ) {
8550
8533
nblocks ++ ;
8551
8534
}
8552
8535
if ((size_t )nblocks > SIZE_MAX / sizeof (basicblock * )) {
@@ -8555,7 +8538,7 @@ assemble(struct compiler *c, int addNone)
8555
8538
}
8556
8539
8557
8540
cfg_builder * g = CFG_BUILDER (c );
8558
- basicblock * entryblock = g -> cfg_entryblock ;
8541
+ basicblock * entryblock = g -> g_entryblock ;
8559
8542
assert (entryblock != NULL );
8560
8543
8561
8544
/* Set firstlineno if it wasn't explicitly set. */
@@ -8974,7 +8957,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
8974
8957
struct instr * inst = & bb -> b_instr [i ];
8975
8958
int oparg = inst -> i_oparg ;
8976
8959
int nextop = i + 1 < bb -> b_iused ? bb -> b_instr [i + 1 ].i_opcode : 0 ;
8977
- if (is_jump (inst ) || is_block_push ( inst )) {
8960
+ if (HAS_TARGET (inst -> i_opcode )) {
8978
8961
/* Skip over empty basic blocks. */
8979
8962
while (inst -> i_target -> b_iused == 0 ) {
8980
8963
inst -> i_target = inst -> i_target -> b_next ;
@@ -9379,7 +9362,7 @@ eliminate_empty_basic_blocks(basicblock *entryblock) {
9379
9362
}
9380
9363
for (int i = 0 ; i < b -> b_iused ; i ++ ) {
9381
9364
struct instr * instr = & b -> b_instr [i ];
9382
- if (is_jump (instr ) || is_block_push ( instr )) {
9365
+ if (HAS_TARGET (instr -> i_opcode )) {
9383
9366
basicblock * target = instr -> i_target ;
9384
9367
while (target -> b_iused == 0 ) {
9385
9368
target = target -> b_next ;
@@ -9458,14 +9441,13 @@ calculate_jump_targets(basicblock *entryblock)
9458
9441
for (int i = 0 ; i < b -> b_iused ; i ++ ) {
9459
9442
struct instr * instr = & b -> b_instr [i ];
9460
9443
assert (instr -> i_target == NULL );
9461
- if (is_jump (instr ) || is_block_push ( instr )) {
9462
- int lbl = instr -> i_target_label . id ;
9444
+ if (HAS_TARGET (instr -> i_opcode )) {
9445
+ int lbl = instr -> i_oparg ;
9463
9446
assert (lbl >= 0 && lbl <= max_label );
9464
9447
instr -> i_target = label2block [lbl ];
9465
9448
assert (instr -> i_target != NULL );
9466
9449
assert (instr -> i_target -> b_label == lbl );
9467
9450
}
9468
- instr -> i_target_label = NO_LABEL ;
9469
9451
}
9470
9452
}
9471
9453
PyMem_Free (label2block );
@@ -9577,7 +9559,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
9577
9559
{
9578
9560
/* Copy all exit blocks without line number that are targets of a jump.
9579
9561
*/
9580
- basicblock * entryblock = g -> cfg_entryblock ;
9562
+ basicblock * entryblock = g -> g_entryblock ;
9581
9563
for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
9582
9564
if (b -> b_iused > 0 && is_jump (& b -> b_instr [b -> b_iused - 1 ])) {
9583
9565
basicblock * target = b -> b_instr [b -> b_iused - 1 ].i_target ;
0 commit comments