diff options
author | H. Peter Anvin <hpa@zytor.com> | 2018-12-10 21:28:59 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2018-12-10 21:28:59 -0800 |
commit | 36e3c707908738ce15dfc75b5a6d57c3e2791e2a (patch) | |
tree | 4b5f1276ff015d6e204b28f2ac245c4a3dc0e8bf /asm/labels.c | |
parent | 2bc04aff90f0d6f2ce66158600592977691619f5 (diff) | |
parent | 54aac9d3c1b501050e6e75823317a4e34d6b2066 (diff) | |
download | nasm-36e3c707908738ce15dfc75b5a6d57c3e2791e2a.tar.gz |
Merge remote-tracking branch 'origin/nasm-2.14.xx'
Resolved Conflicts:
asm/labels.c
include/error.h
version
Diffstat (limited to 'asm/labels.c')
-rw-r--r-- | asm/labels.c | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/asm/labels.c b/asm/labels.c index 4e69d99a..cffe1027 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -109,9 +109,11 @@ union label { /* actual label structures */ int32_t subsection; /* Available for ofmt->herelabel() */ int64_t offset; int64_t size; + int64_t defined; /* 0 if undefined, passn+1 for when defn seen */ char *label, *mangled, *special; + const char *def_file; /* Where defined */ + int32_t def_line; enum label_type type, mangled_type; - bool defined; } defn; struct { int32_t movingon; @@ -369,7 +371,7 @@ handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset) location.offset = *offset; } else { /* Keep a separate offset for the new segment */ - *offset = switch_segment(newseg); + *offset = switch_segment(newseg); } } } @@ -433,6 +435,13 @@ void define_label(const char *label, int32_t segment, union label *lptr; bool created, changed; int64_t size; + int64_t lastdef; + + /* + * The backend may invoke this before pass 1, so treat that as + * a special "pass". + */ + const int64_t lpass = pass0 + 1; /* * Phase errors here can be one of two types: a new label appears, @@ -441,17 +450,26 @@ void define_label(const char *label, int32_t segment, */ lptr = find_label(label, true, &created); + lastdef = lptr->defn.defined; + if (segment) { /* We are actually defining this label */ - if (lptr->defn.type == LBL_EXTERN) /* auto-promote EXTERN to GLOBAL */ + if (lptr->defn.type == LBL_EXTERN) { + /* auto-promote EXTERN to GLOBAL */ lptr->defn.type = LBL_GLOBAL; + lastdef = 0; /* We are "re-creating" this label */ + } } else { /* It's a pseudo-segment (extern, common) */ segment = lptr->defn.segment ? lptr->defn.segment : seg_alloc(); } - if (lptr->defn.defined || lptr->defn.type == LBL_BACKEND) { - /* We have seen this on at least one previous pass */ + if (lastdef || lptr->defn.type == LBL_BACKEND) { + /* + * We have seen this on at least one previous pass, or + * potentially earlier in this same pass (in which case we + * will probably error out further down.) + */ mangle_label_name(lptr); handle_herelabel(lptr, &segment, &offset); } @@ -469,27 +487,51 @@ void define_label(const char *label, int32_t segment, size = 0; /* This is a hack... */ } - changed = created || !lptr->defn.defined || + changed = created || !lastdef || lptr->defn.segment != segment || - lptr->defn.offset != offset || lptr->defn.size != size; + lptr->defn.offset != offset || + lptr->defn.size != size; global_offset_changed += changed; - /* - * This probably should be ERR_NONFATAL, but not quite yet. As a - * special case, LBL_SPECIAL symbols are allowed to be changed - * even during the last pass. - */ - if (changed && pass0 > 1 && lptr->defn.type != LBL_SPECIAL) { - nasm_warn("label `%s' %s during code generation", - lptr->defn.label, created ? "defined" : "changed"); + if (changed) { + if (lastdef == lpass) { + int32_t saved_line = 0; + const char *saved_fname = NULL; + + /* + * Defined elsewhere in the program, seen in this pass. + */ + nasm_error(ERR_NONFATAL, + "label `%s' inconsistently redefined", + lptr->defn.label); + + src_get(&saved_line, &saved_fname); + src_set(lptr->defn.def_line, lptr->defn.def_file); + nasm_error(ERR_NOTE, "label `%s' originally defined here", + lptr->defn.label); + src_set(saved_line, saved_fname); + } else if (pass0 > 1 && lptr->defn.type != LBL_SPECIAL) { + /* + * This probably should be ERR_NONFATAL, but not quite yet. As a + * special case, LBL_SPECIAL symbols are allowed to be changed + * even during the last pass. + */ + nasm_warn("label `%s' %s during code generation", + lptr->defn.label, + created ? "defined" : "changed"); + } } lptr->defn.segment = segment; lptr->defn.offset = offset; lptr->defn.size = size; - lptr->defn.defined = true; + lptr->defn.defined = lpass; + + if (changed || lastdef != lpass) + src_get(&lptr->defn.def_line, &lptr->defn.def_file); - out_symdef(lptr); + if (lastdef != lpass) + out_symdef(lptr); } /* |