summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2021-07-02 14:10:11 (GMT)
committerGitHub <noreply@github.com>2021-07-02 14:10:11 (GMT)
commit98eee94421dcb42c15f2d7fc4cd21357722fbe2a (patch)
tree45a158d1e97f0b29d24ded80122559b50cc858f5 /Python/compile.c
parent943e77d42d3f84b581f32c05f1fc8c05366b8ed3 (diff)
downloadcpython-98eee94421dcb42c15f2d7fc4cd21357722fbe2a.zip
cpython-98eee94421dcb42c15f2d7fc4cd21357722fbe2a.tar.gz
cpython-98eee94421dcb42c15f2d7fc4cd21357722fbe2a.tar.bz2
bpo-43950: Add code.co_positions (PEP 657) (GH-26955)
This PR is part of PEP 657 and augments the compiler to emit ending line numbers as well as starting and ending columns from the AST into compiled code objects. This allows bytecodes to be correlated to the exact source code ranges that generated them. This information is made available through the following public APIs: * The `co_positions` method on code objects. * The C API function `PyCode_Addr2Location`. Co-authored-by: Batuhan Taskaya <isidentical@gmail.com> Co-authored-by: Ammar Askar <ammar@ammaraskar.com>
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c271
1 files changed, 208 insertions, 63 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 99e500f..0bce6ce 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -40,6 +40,7 @@
#define DEFAULT_BLOCKS 8
#define DEFAULT_CODE_SIZE 128
#define DEFAULT_LNOTAB_SIZE 16
+#define DEFAULT_CNOTAB_SIZE 0
#define COMP_GENEXP 0
#define COMP_LISTCOMP 1
@@ -90,6 +91,9 @@ struct instr {
/* target block when exception is raised, should not be set by front-end. */
struct basicblock_ *i_except;
int i_lineno;
+ int i_end_lineno;
+ int i_col_offset;
+ int i_end_col_offset;
};
typedef struct excepthandler {
@@ -963,6 +967,19 @@ compiler_next_instr(basicblock *b)
(c)->u->u_end_lineno = (x)->end_lineno; \
(c)->u->u_end_col_offset = (x)->end_col_offset;
+// Artificial instructions
+#define UNSET_LOC(c) \
+ (c)->u->u_lineno = -1; \
+ (c)->u->u_col_offset = -1; \
+ (c)->u->u_end_lineno = -1; \
+ (c)->u->u_end_col_offset = -1;
+
+#define COPY_INSTR_LOC(old, new) \
+ (new).i_lineno = (old).i_lineno; \
+ (new).i_col_offset = (old).i_col_offset; \
+ (new).i_end_lineno = (old).i_end_lineno; \
+ (new).i_end_col_offset = (old).i_end_col_offset;
+
/* Return the stack effect of opcode with argument oparg.
Some opcodes have different stack effect when jump to the target and
@@ -1266,7 +1283,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
*/
static int
-compiler_addop_line(struct compiler *c, int opcode, int line)
+compiler_addop_line(struct compiler *c, int opcode, int line,
+ int end_line, int col_offset, int end_col_offset)
{
basicblock *b;
struct instr *i;
@@ -1282,19 +1300,23 @@ compiler_addop_line(struct compiler *c, int opcode, int line)
if (opcode == RETURN_VALUE)
b->b_return = 1;
i->i_lineno = line;
+ i->i_end_lineno = end_line;
+ i->i_col_offset = col_offset;
+ i->i_end_col_offset = end_col_offset;
return 1;
}
static int
compiler_addop(struct compiler *c, int opcode)
{
- return compiler_addop_line(c, opcode, c->u->u_lineno);
+ return compiler_addop_line(c, opcode, c->u->u_lineno, c->u->u_end_lineno,
+ c->u->u_col_offset, c->u->u_end_col_offset);
}
static int
compiler_addop_noline(struct compiler *c, int opcode)
{
- return compiler_addop_line(c, opcode, -1);
+ return compiler_addop_line(c, opcode, -1, 0, 0, 0);
}
@@ -1488,7 +1510,9 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict,
*/
static int
-compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg, int lineno)
+compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg,
+ int lineno, int end_lineno,
+ int col_offset, int end_col_offset)
{
struct instr *i;
int off;
@@ -1510,22 +1534,30 @@ compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg, int line
i->i_opcode = opcode;
i->i_oparg = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
i->i_lineno = lineno;
+ i->i_end_lineno = end_lineno;
+ i->i_col_offset = col_offset;
+ i->i_end_col_offset = end_col_offset;
return 1;
}
static int
compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg)
{
- return compiler_addop_i_line(c, opcode, oparg, c->u->u_lineno);
+ return compiler_addop_i_line(c, opcode, oparg,
+ c->u->u_lineno, c->u->u_end_lineno,
+ c->u->u_col_offset, c->u->u_end_col_offset);
}
static int
compiler_addop_i_noline(struct compiler *c, int opcode, Py_ssize_t oparg)
{
- return compiler_addop_i_line(c, opcode, oparg, -1);
+ return compiler_addop_i_line(c, opcode, oparg, -1, 0, 0, 0);
}
-static int add_jump_to_block(basicblock *b, int opcode, int lineno, basicblock *target)
+static int add_jump_to_block(basicblock *b, int opcode,
+ int lineno, int end_lineno,
+ int col_offset, int end_col_offset,
+ basicblock *target)
{
assert(HAS_ARG(opcode));
assert(b != NULL);
@@ -1539,19 +1571,24 @@ static int add_jump_to_block(basicblock *b, int opcode, int lineno, basicblock *
i->i_opcode = opcode;
i->i_target = target;
i->i_lineno = lineno;
+ i->i_end_lineno = end_lineno;
+ i->i_col_offset = col_offset;
+ i->i_end_col_offset = end_col_offset;
return 1;
}
static int
compiler_addop_j(struct compiler *c, int opcode, basicblock *b)
{
- return add_jump_to_block(c->u->u_curblock, opcode, c->u->u_lineno, b);
+ return add_jump_to_block(c->u->u_curblock, opcode, c->u->u_lineno,
+ c->u->u_end_lineno, c->u->u_col_offset,
+ c->u->u_end_col_offset, b);
}
static int
compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b)
{
- return add_jump_to_block(c->u->u_curblock, opcode, -1, b);
+ return add_jump_to_block(c->u->u_curblock, opcode, -1, 0, 0, 0, b);
}
/* NEXT_BLOCK() creates an implicit jump from the current block
@@ -1834,7 +1871,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
/* The finally block should appear to execute after the
* statement causing the unwinding, so make the unwinding
* instruction artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
return 1;
case FINALLY_END:
@@ -1870,7 +1907,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
/* The exit block should appear to execute after the
* statement causing the unwinding, so make the unwinding
* instruction artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
return 1;
case HANDLER_CLEANUP:
@@ -2522,7 +2559,7 @@ compiler_class(struct compiler *c, stmt_ty s)
return 0;
}
/* The following code is artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
/* Return __classcell__ if it is referenced, otherwise return None */
if (c->u->u_ste->ste_needs_class_closure) {
/* Store __classcell__ into class namespace & return it */
@@ -2913,7 +2950,7 @@ compiler_for(struct compiler *c, stmt_ty s)
VISIT(c, expr, s->v.For.target);
VISIT_SEQ(c, stmt, s->v.For.body);
/* Mark jump as artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
compiler_use_next_block(c, cleanup);
@@ -2966,7 +3003,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
/* Except block for __anext__ */
compiler_use_next_block(c, except);
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP(c, END_ASYNC_FOR);
/* `else` block */
@@ -3153,7 +3190,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
/* `finally` block */
compiler_use_next_block(c, end);
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP_JUMP(c, SETUP_CLEANUP, cleanup);
ADDOP(c, PUSH_EXC_INFO);
if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL))
@@ -3221,7 +3258,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
n = asdl_seq_LEN(s->v.Try.handlers);
compiler_use_next_block(c, except);
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP_JUMP(c, SETUP_CLEANUP, cleanup);
ADDOP(c, PUSH_EXC_INFO);
/* Runtime will push a block here, so we need to account for that */
@@ -3280,7 +3317,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
ADDOP(c, POP_BLOCK);
ADDOP(c, POP_EXCEPT);
/* name = None; del name; # Mark as artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP_LOAD_CONST(c, Py_None);
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
compiler_nameop(c, handler->v.ExceptHandler.name, Del);
@@ -3290,7 +3327,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
compiler_use_next_block(c, cleanup_end);
/* name = None; del name; # Mark as artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP_LOAD_CONST(c, Py_None);
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
@@ -3313,7 +3350,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
/* name = None; del name; # Mark as artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP(c, POP_BLOCK);
ADDOP(c, POP_EXCEPT);
ADDOP_JUMP(c, JUMP_FORWARD, end);
@@ -3321,7 +3358,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
compiler_use_next_block(c, except);
}
/* Mark as artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
compiler_pop_fblock(c, EXCEPTION_HANDLER, NULL);
ADDOP_I(c, RERAISE, 0);
compiler_use_next_block(c, cleanup);
@@ -3542,7 +3579,7 @@ compiler_visit_stmt_expr(struct compiler *c, expr_ty value)
VISIT(c, expr, value);
/* Mark POP_TOP as artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP(c, POP_TOP);
return 1;
}
@@ -4896,7 +4933,7 @@ compiler_async_comprehension_generator(struct compiler *c,
compiler_pop_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start);
compiler_use_next_block(c, except);
- //c->u->u_lineno = -1;
+ //UNSET_LOC(c);
ADDOP(c, END_ASYNC_FOR);
@@ -5076,7 +5113,7 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k)
static int
compiler_with_except_finish(struct compiler *c, basicblock * cleanup) {
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
basicblock *exit;
exit = compiler_new_block(c);
if (exit == NULL)
@@ -5271,7 +5308,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
/* Mark all following code as artificial */
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
ADDOP(c, POP_BLOCK);
compiler_pop_fblock(c, WITH, block);
@@ -6546,12 +6583,18 @@ struct assembler {
int a_offset; /* offset into bytecode */
int a_nblocks; /* number of reachable blocks */
PyObject *a_lnotab; /* bytes containing lnotab */
+ PyObject* a_enotab; /* bytes containing enotab */
+ PyObject* a_cnotab; /* bytes containing cnotab */
int a_lnotab_off; /* offset into lnotab */
+ int a_enotab_off; /* offset into enotab */
PyObject *a_except_table; /* bytes containing exception table */
int a_except_table_off; /* offset into exception table */
int a_prevlineno; /* lineno of last emitted line in line table */
+ int a_prev_end_lineno; /* end_lineno of last emitted line in line table */
int a_lineno; /* lineno of last emitted instruction */
+ int a_end_lineno; /* end_lineno of last emitted instruction */
int a_lineno_start; /* bytecode start offset of current lineno */
+ int a_end_lineno_start; /* bytecode start offset of current end_lineno */
basicblock *a_entry;
};
@@ -6649,7 +6692,10 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno)
{
memset(a, 0, sizeof(struct assembler));
a->a_prevlineno = a->a_lineno = firstlineno;
+ a->a_prev_end_lineno = a->a_end_lineno = firstlineno;
a->a_lnotab = NULL;
+ a->a_enotab = NULL;
+ a->a_cnotab = NULL;
a->a_except_table = NULL;
a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE);
if (a->a_bytecode == NULL) {
@@ -6659,6 +6705,14 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno)
if (a->a_lnotab == NULL) {
goto error;
}
+ a->a_enotab = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
+ if (a->a_enotab == NULL) {
+ goto error;
+ }
+ a->a_cnotab = PyBytes_FromStringAndSize(NULL, DEFAULT_CNOTAB_SIZE);
+ if (a->a_cnotab == NULL) {
+ goto error;
+ }
a->a_except_table = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
if (a->a_except_table == NULL) {
goto error;
@@ -6671,6 +6725,8 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno)
error:
Py_XDECREF(a->a_bytecode);
Py_XDECREF(a->a_lnotab);
+ Py_XDECREF(a->a_enotab);
+ Py_XDECREF(a->a_cnotab);
Py_XDECREF(a->a_except_table);
return 0;
}
@@ -6680,6 +6736,8 @@ assemble_free(struct assembler *a)
{
Py_XDECREF(a->a_bytecode);
Py_XDECREF(a->a_lnotab);
+ Py_XDECREF(a->a_enotab);
+ Py_XDECREF(a->a_cnotab);
Py_XDECREF(a->a_except_table);
}
@@ -6695,18 +6753,21 @@ blocksize(basicblock *b)
}
static int
-assemble_emit_linetable_pair(struct assembler *a, int bdelta, int ldelta)
+assemble_emit_table_pair(struct assembler* a, PyObject** table, int* offset,
+ int left, int right)
{
- Py_ssize_t len = PyBytes_GET_SIZE(a->a_lnotab);
- if (a->a_lnotab_off + 2 >= len) {
- if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0)
+ Py_ssize_t len = PyBytes_GET_SIZE(*table);
+ if (*offset + 2 >= len) {
+ if (_PyBytes_Resize(table, len * 2) < 0)
return 0;
}
- unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(a->a_lnotab);
- lnotab += a->a_lnotab_off;
- a->a_lnotab_off += 2;
- *lnotab++ = bdelta;
- *lnotab++ = ldelta;
+ unsigned char* table_entry = (unsigned char*)PyBytes_AS_STRING(*table);
+
+ table_entry += *offset;
+ *offset += 2;
+
+ *table_entry++ = left;
+ *table_entry++ = right;
return 1;
}
@@ -6961,27 +7022,28 @@ assemble_exception_table(struct assembler *a)
* Objects/lnotab_notes.txt for the description of the line number table. */
static int
-assemble_line_range(struct assembler *a)
+assemble_line_range(struct assembler* a, int current, PyObject** table,
+ int* prev, int* start, int* offset)
{
int ldelta, bdelta;
- bdelta = (a->a_offset - a->a_lineno_start) * 2;
+ bdelta = (a->a_offset - *start) * 2;
if (bdelta == 0) {
return 1;
}
- if (a->a_lineno < 0) {
+ if (current < 0) {
ldelta = -128;
}
else {
- ldelta = a->a_lineno - a->a_prevlineno;
- a->a_prevlineno = a->a_lineno;
+ ldelta = current - *prev;
+ *prev = current;
while (ldelta > 127) {
- if (!assemble_emit_linetable_pair(a, 0, 127)) {
+ if (!assemble_emit_table_pair(a, table, offset, 0, 127)) {
return 0;
}
ldelta -= 127;
}
while (ldelta < -127) {
- if (!assemble_emit_linetable_pair(a, 0, -127)) {
+ if (!assemble_emit_table_pair(a, table, offset, 0, -127)) {
return 0;
}
ldelta += 127;
@@ -6989,32 +7051,82 @@ assemble_line_range(struct assembler *a)
}
assert(-128 <= ldelta && ldelta < 128);
while (bdelta > 254) {
- if (!assemble_emit_linetable_pair(a, 254, ldelta)) {
+ if (!assemble_emit_table_pair(a, table, offset, 254, ldelta)) {
return 0;
}
- ldelta = a->a_lineno < 0 ? -128 : 0;
+ ldelta = current < 0 ? -128 : 0;
bdelta -= 254;
}
- if (!assemble_emit_linetable_pair(a, bdelta, ldelta)) {
+ if (!assemble_emit_table_pair(a, table, offset, bdelta, ldelta)) {
return 0;
}
- a->a_lineno_start = a->a_offset;
+ *start = a->a_offset;
return 1;
}
static int
-assemble_lnotab(struct assembler *a, struct instr *i)
+assemble_start_line_range(struct assembler* a) {
+ return assemble_line_range(a, a->a_lineno, &a->a_lnotab,
+ &a->a_prevlineno, &a->a_lineno_start, &a->a_lnotab_off);
+}
+
+static int
+assemble_end_line_range(struct assembler* a) {
+ return assemble_line_range(a, a->a_end_lineno, &a->a_enotab,
+ &a->a_prev_end_lineno, &a->a_end_lineno_start, &a->a_enotab_off);
+}
+
+static int
+assemble_lnotab(struct assembler* a, struct instr* i)
{
if (i->i_lineno == a->a_lineno) {
return 1;
}
- if (!assemble_line_range(a)) {
+ if (!assemble_start_line_range(a)) {
return 0;
}
a->a_lineno = i->i_lineno;
return 1;
}
+static int
+assemble_enotab(struct assembler* a, struct instr* i)
+{
+ if (i->i_end_lineno == a->a_end_lineno) {
+ return 1;
+ }
+ if (!assemble_end_line_range(a)) {
+ return 0;
+ }
+ a->a_end_lineno = i->i_end_lineno;
+ return 1;
+}
+
+static int
+assemble_cnotab(struct assembler* a, struct instr* i, int instr_size)
+{
+ Py_ssize_t len = PyBytes_GET_SIZE(a->a_cnotab);
+ // TODO: Allocate more memory than just what we immediately need
+ // like a_lnotab does.
+ if (_PyBytes_Resize(&a->a_cnotab, len + (instr_size * 2)) < 0) {
+ return 0;
+ }
+
+ unsigned char* cnotab = (unsigned char*)PyBytes_AS_STRING(a->a_cnotab);
+ cnotab += len;
+
+ for (int j = 0; j < instr_size; j++) {
+ if (i->i_col_offset > 255 || i->i_end_col_offset > 255) {
+ *cnotab++ = 0;
+ *cnotab++ = 0;
+ continue;
+ }
+ *cnotab++ = i->i_col_offset + 1;
+ *cnotab++ = i->i_end_col_offset + 1;
+ }
+ return 1;
+}
+
/* assemble_emit()
Extend the bytecode with a new instruction.
@@ -7030,8 +7142,15 @@ assemble_emit(struct assembler *a, struct instr *i)
arg = i->i_oparg;
size = instrsize(arg);
- if (i->i_lineno && !assemble_lnotab(a, i))
+ if (i->i_lineno && !assemble_lnotab(a, i)) {
return 0;
+ }
+ if (!assemble_enotab(a, i)) {
+ return 0;
+ }
+ if (!assemble_cnotab(a, i, size)) {
+ return 0;
+ }
if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
if (len > PY_SSIZE_T_MAX / 2)
return 0;
@@ -7315,6 +7434,8 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
.code = a->a_bytecode,
.firstlineno = c->u->u_firstlineno,
.linetable = a->a_lnotab,
+ .endlinetable = a->a_enotab,
+ .columntable = a->a_cnotab,
.consts = consts,
.names = names,
@@ -7478,6 +7599,9 @@ insert_prefix_instructions(struct compiler *c, basicblock *entryblock,
// This will get fixed in offset_derefs().
.i_oparg = oldindex,
.i_lineno = -1,
+ .i_col_offset = -1,
+ .i_end_lineno = -1,
+ .i_end_col_offset = -1,
.i_target = NULL,
};
if (insert_instruction(entryblock, ncellsused, &make_cell) < 0) {
@@ -7505,6 +7629,9 @@ insert_prefix_instructions(struct compiler *c, basicblock *entryblock,
.i_opcode = GEN_START,
.i_oparg = kind,
.i_lineno = -1,
+ .i_col_offset = -1,
+ .i_end_lineno = -1,
+ .i_end_col_offset = -1,
.i_target = NULL,
};
if (insert_instruction(entryblock, 0, &gen_start) < 0) {
@@ -7602,7 +7729,7 @@ assemble(struct compiler *c, int addNone)
block ends with a jump or return b_next shouldn't set.
*/
if (!c->u->u_curblock->b_return) {
- c->u->u_lineno = -1;
+ UNSET_LOC(c);
if (addNone)
ADDOP_LOAD_CONST(c, Py_None);
ADDOP(c, RETURN_VALUE);
@@ -7707,19 +7834,25 @@ assemble(struct compiler *c, int addNone)
if (!assemble_exception_table(&a)) {
goto error;
}
- if (!assemble_line_range(&a)) {
+ if (_PyBytes_Resize(&a.a_except_table, a.a_except_table_off) < 0) {
goto error;
}
-
+ if (!assemble_start_line_range(&a)) {
+ return 0;
+ }
if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) {
goto error;
}
-
- if (_PyBytes_Resize(&a.a_except_table, a.a_except_table_off) < 0) {
+ if (!merge_const_one(c, &a.a_lnotab)) {
goto error;
}
-
- if (!merge_const_one(c, &a.a_lnotab)) {
+ if (!assemble_end_line_range(&a)) {
+ return 0;
+ }
+ if (_PyBytes_Resize(&a.a_enotab, a.a_enotab_off) < 0) {
+ goto error;
+ }
+ if (!merge_const_one(c, &a.a_enotab)) {
goto error;
}
if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0) {
@@ -7848,7 +7981,11 @@ eliminate_jump_to_jump(basicblock *bb, int opcode) {
return 0;
}
int lineno = target->i_lineno;
- if (add_jump_to_block(bb, opcode, lineno, target->i_target) == 0) {
+ int end_lineno = target->i_end_lineno;
+ int col_offset = target->i_col_offset;
+ int end_col_offset = target->i_end_col_offset;
+ if (add_jump_to_block(bb, opcode, lineno, end_lineno, col_offset,
+ end_col_offset, target->i_target) == 0) {
return -1;
}
assert (bb->b_iused >= 2);
@@ -8127,7 +8264,7 @@ clean_basic_block(basicblock *bb) {
if (src < bb->b_iused - 1) {
int next_lineno = bb->b_instr[src+1].i_lineno;
if (next_lineno < 0 || next_lineno == lineno) {
- bb->b_instr[src+1].i_lineno = lineno;
+ COPY_INSTR_LOC(bb->b_instr[src], bb->b_instr[src+1]);
continue;
}
}
@@ -8262,19 +8399,27 @@ propogate_line_numbers(struct assembler *a) {
if (b->b_iused == 0) {
continue;
}
- int prev_lineno = -1;
+
+ // Not a real instruction, only to store positions
+ // from previous instructions and propagate them.
+ struct instr prev_instr = {
+ .i_lineno = -1,
+ .i_col_offset = -1,
+ .i_end_lineno = -1,
+ .i_end_col_offset = -1,
+ };
for (int i = 0; i < b->b_iused; i++) {
if (b->b_instr[i].i_lineno < 0) {
- b->b_instr[i].i_lineno = prev_lineno;
+ COPY_INSTR_LOC(prev_instr, b->b_instr[i]);
}
else {
- prev_lineno = b->b_instr[i].i_lineno;
+ COPY_INSTR_LOC(b->b_instr[i], prev_instr);
}
}
if (!b->b_nofallthrough && b->b_next->b_predecessors == 1) {
assert(b->b_next->b_iused);
if (b->b_next->b_instr[0].i_lineno < 0) {
- b->b_next->b_instr[0].i_lineno = prev_lineno;
+ COPY_INSTR_LOC(prev_instr, b->b_next->b_instr[0]);
}
}
if (is_jump(&b->b_instr[b->b_iused-1])) {
@@ -8288,7 +8433,7 @@ propogate_line_numbers(struct assembler *a) {
basicblock *target = b->b_instr[b->b_iused-1].i_target;
if (target->b_predecessors == 1) {
if (target->b_instr[0].i_lineno < 0) {
- target->b_instr[0].i_lineno = prev_lineno;
+ COPY_INSTR_LOC(prev_instr, target->b_instr[0]);
}
}
}
@@ -8391,7 +8536,7 @@ ensure_exits_have_lineno(struct compiler *c)
if (new_target == NULL) {
return -1;
}
- new_target->b_instr[0].i_lineno = b->b_instr[b->b_iused-1].i_lineno;
+ COPY_INSTR_LOC(b->b_instr[b->b_iused-1], new_target->b_instr[0]);
b->b_instr[b->b_iused-1].i_target = new_target;
}
}
@@ -8412,7 +8557,7 @@ ensure_exits_have_lineno(struct compiler *c)
if (!b->b_nofallthrough && b->b_next && b->b_iused > 0) {
if (is_exit_without_lineno(b->b_next)) {
assert(b->b_next->b_iused > 0);
- b->b_next->b_instr[0].i_lineno = b->b_instr[b->b_iused-1].i_lineno;
+ COPY_INSTR_LOC(b->b_instr[b->b_iused-1], b->b_next->b_instr[0]);
}
}
}