Skip to content

Commit 8dfbd2d

Browse files
committed
py: Make inline assembler raise proper SyntaxError exception on error.
Also gives line number of location of error. Very useful!
1 parent 1bf5a02 commit 8dfbd2d

3 files changed

Lines changed: 41 additions & 34 deletions

File tree

py/compile.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@ STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const cha
9292
mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
9393
// we don't have a 'block' name, so just pass the NULL qstr to indicate this
9494
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
95-
mp_obj_exception_add_traceback(exc, comp->source_file, (mp_uint_t)((mp_parse_node_struct_t*)pn)->source_line, MP_QSTR_NULL);
95+
mp_obj_exception_add_traceback(exc, comp->source_file, (mp_uint_t)((mp_parse_node_struct_t*)pn)->source_line, comp->scope_cur->simple_name);
9696
} else {
9797
// we don't have a line number, so just pass 0
98-
mp_obj_exception_add_traceback(exc, comp->source_file, 0, MP_QSTR_NULL);
98+
mp_obj_exception_add_traceback(exc, comp->source_file, 0, comp->scope_cur->simple_name);
9999
}
100100
comp->compile_error = exc;
101101
}
@@ -3426,7 +3426,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
34263426
}
34273427

34283428
if (comp->pass > MP_PASS_SCOPE) {
3429-
EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
3429+
EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur, &comp->compile_error);
34303430
}
34313431

34323432
// get the function definition parse node
@@ -3441,6 +3441,9 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
34413441
mp_parse_node_t *pn_params;
34423442
int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
34433443
scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
3444+
if (comp->compile_error != MP_OBJ_NULL) {
3445+
goto inline_asm_error;
3446+
}
34443447
}
34453448

34463449
assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
@@ -3519,14 +3522,21 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
35193522
EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
35203523
}
35213524
}
3525+
3526+
if (comp->compile_error != MP_OBJ_NULL) {
3527+
pns = pns2; // this is the parse node that had the error
3528+
goto inline_asm_error;
3529+
}
35223530
}
35233531

35243532
if (comp->pass > MP_PASS_SCOPE) {
3525-
bool success = EMIT_INLINE_ASM(end_pass);
3526-
if (!success) {
3527-
// TODO get proper exception from inline assembler
3528-
compile_syntax_error(comp, MP_PARSE_NODE_NULL, "inline assembler error");
3529-
}
3533+
EMIT_INLINE_ASM(end_pass);
3534+
}
3535+
3536+
if (comp->compile_error != MP_OBJ_NULL) {
3537+
// inline assembler had an error; add traceback to its exception
3538+
inline_asm_error:
3539+
mp_obj_exception_add_traceback(comp->compile_error, comp->source_file, (mp_uint_t)pns->source_line, comp->scope_cur->simple_name);
35303540
}
35313541
}
35323542
#endif

py/emit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ void emit_native_arm_free(emit_t *emit);
192192
typedef struct _emit_inline_asm_t emit_inline_asm_t;
193193

194194
typedef struct _emit_inline_asm_method_table_t {
195-
void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope);
196-
bool (*end_pass)(emit_inline_asm_t *emit);
195+
void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope, mp_obj_t *error_slot);
196+
void (*end_pass)(emit_inline_asm_t *emit);
197197
mp_uint_t (*count_params)(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params);
198198
void (*label)(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id);
199199
void (*align)(emit_inline_asm_t *emit, mp_uint_t align);

py/emitinlinethumb.c

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,19 @@ typedef enum {
4444

4545
struct _emit_inline_asm_t {
4646
uint16_t pass;
47-
uint16_t success;
4847
scope_t *scope;
48+
mp_obj_t *error_slot;
4949
mp_uint_t max_num_labels;
5050
qstr *label_lookup;
5151
asm_thumb_t *as;
5252
};
5353

54-
STATIC void emit_inline_thumb_error(emit_inline_asm_t *emit, const char *fmt, ...) {
55-
printf("SyntaxError: ");
56-
emit->success = false;
57-
va_list ap;
58-
va_start(ap, fmt);
59-
vprintf(fmt, ap);
60-
va_end(ap);
54+
STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const char *msg) {
55+
*emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
56+
}
57+
58+
STATIC void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) {
59+
*emit->error_slot = exc;
6160
}
6261

6362
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
@@ -75,39 +74,37 @@ void emit_inline_thumb_free(emit_inline_asm_t *emit) {
7574
m_del_obj(emit_inline_asm_t, emit);
7675
}
7776

78-
STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope) {
77+
STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope, mp_obj_t *error_slot) {
7978
emit->pass = pass;
80-
emit->success = true;
8179
emit->scope = scope;
80+
emit->error_slot = error_slot;
8281
asm_thumb_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_THUMB_PASS_EMIT : ASM_THUMB_PASS_COMPUTE);
8382
asm_thumb_entry(emit->as, 0);
8483
}
8584

86-
STATIC bool emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
85+
STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
8786
asm_thumb_exit(emit->as);
8887
asm_thumb_end_pass(emit->as);
8988

9089
if (emit->pass == MP_PASS_EMIT) {
9190
void *f = asm_thumb_get_code(emit->as);
9291
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f, asm_thumb_get_code_size(emit->as), emit->scope->num_pos_args, 0);
9392
}
94-
95-
return emit->success;
9693
}
9794

9895
STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) {
9996
if (n_params > 4) {
100-
emit_inline_thumb_error(emit, "can only have up to 4 parameters to inline thumb assembly\n");
97+
emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly");
10198
return 0;
10299
}
103100
for (mp_uint_t i = 0; i < n_params; i++) {
104101
if (!MP_PARSE_NODE_IS_ID(pn_params[i])) {
105-
emit_inline_thumb_error(emit, "parameter to inline assembler must be an identifier\n");
102+
emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
106103
return 0;
107104
}
108105
const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i]));
109106
if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
110-
emit_inline_thumb_error(emit, "parameter %d to inline assembler must be r%d\n", i + 1, i);
107+
emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
111108
return 0;
112109
}
113110
}
@@ -161,26 +158,26 @@ STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_n
161158
const reg_name_t *r = &reg_name_table[i];
162159
if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) {
163160
if (r->reg > max_reg) {
164-
emit_inline_thumb_error(emit, "'%s' expects at most r%d\n", op, max_reg);
161+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects at most r%d", op, max_reg));
165162
return 0;
166163
} else {
167164
return r->reg;
168165
}
169166
}
170167
}
171168
}
172-
emit_inline_thumb_error(emit, "'%s' expects a register\n", op);
169+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a register", op));
173170
return 0;
174171
}
175172

176173
STATIC int get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, int fit_mask) {
177174
if (!MP_PARSE_NODE_IS_SMALL_INT(pn)) {
178-
emit_inline_thumb_error(emit, "'%s' expects an integer\n", op);
175+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an integer", op));
179176
return 0;
180177
}
181178
int i = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
182179
if ((i & (~fit_mask)) != 0) {
183-
emit_inline_thumb_error(emit, "'%s' integer 0x%x does not fit in mask 0x%x\n", op, i, fit_mask);
180+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' integer 0x%x does not fit in mask 0x%x", op, i, fit_mask));
184181
return 0;
185182
}
186183
return i;
@@ -204,13 +201,13 @@ STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_
204201
return true;
205202

206203
bad_arg:
207-
emit_inline_thumb_error(emit, "'%s' expects an address of the form [a, b]\n", op);
204+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an address of the form [a, b]", op));
208205
return false;
209206
}
210207

211208
STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
212209
if (!MP_PARSE_NODE_IS_ID(pn)) {
213-
emit_inline_thumb_error(emit, "'%s' expects a label\n", op);
210+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a label", op));
214211
return 0;
215212
}
216213
qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
@@ -221,7 +218,7 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_
221218
}
222219
// only need to have the labels on the last pass
223220
if (emit->pass == MP_PASS_EMIT) {
224-
emit_inline_thumb_error(emit, "label '%s' not defined\n", qstr_str(label_qstr));
221+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "label '%s' not defined", qstr_str(label_qstr)));
225222
}
226223
return 0;
227224
}
@@ -450,7 +447,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
450447
return;
451448

452449
unknown_op:
453-
emit_inline_thumb_error(emit, "unsupported Thumb instruction '%s' with %d arguments\n", op_str, n_args);
450+
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "unsupported Thumb instruction '%s' with %d arguments", op_str, n_args));
454451
}
455452

456453
const emit_inline_asm_method_table_t emit_inline_thumb_method_table = {

0 commit comments

Comments
 (0)