summaryrefslogtreecommitdiff
path: root/labels.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-06-27 16:30:00 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-06-27 16:30:00 -0700
commitaeb0e0e9f1e7e9b32a8f17f2259311f6e9207aa6 (patch)
tree65772775e0b109c6a46f7b8860942ed3b50bde37 /labels.c
parent3512d717489cc1d01e326fd971e42ab5a5c96661 (diff)
downloadnasm-aeb0e0e9f1e7e9b32a8f17f2259311f6e9207aa6.tar.gz
BR 2781900: handle common labels while optimizing
When optimizing, we have to keep track of common labels, since a common symbol cannot be optimized -- only the linker will know where it will end up. In that sense it is similar to an EXTERN symbol. Thus, allow them to be entered in the symbol table but make sure we don't holler too hard on redefinition. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'labels.c')
-rw-r--r--labels.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/labels.c b/labels.c
index 9a7fc615..49792d28 100644
--- a/labels.c
+++ b/labels.c
@@ -47,9 +47,10 @@
#endif
/* values for label.defn.is_global */
-#define DEFINED_BIT 1
-#define GLOBAL_BIT 2
-#define EXTERN_BIT 4
+#define DEFINED_BIT 1
+#define GLOBAL_BIT 2
+#define EXTERN_BIT 4
+#define COMMON_BIT 8
#define NOT_DEFINED_YET 0
#define TYPE_MASK 3
@@ -209,7 +210,9 @@ void redefine_label(char *label, int32_t segment, int64_t offset, char *special,
prevlabel = lptr->defn.label;
}
- if (lptr->defn.offset != offset) global_offset_changed++;
+ if (lptr->defn.offset != offset)
+ global_offset_changed++;
+
lptr->defn.offset = offset;
lptr->defn.segment = segment;
@@ -270,9 +273,10 @@ void define_label(char *label, int32_t segment, int64_t offset, char *special,
if (isextrn)
lptr->defn.is_global |= EXTERN_BIT;
- if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */
+ if (!islocalchar(label[0]) && is_norm) {
+ /* not local, but not special either */
prevlabel = lptr->defn.label;
- else if (islocal(label) && !*prevlabel) {
+ } else if (islocal(label) && !*prevlabel) {
error(ERR_NONFATAL, "attempt to define a local label before any"
" non-local labels");
}
@@ -321,26 +325,32 @@ void define_common(char *label, int32_t segment, int32_t size, char *special,
union label *lptr;
lptr = find_label(label, 1);
- if (lptr->defn.is_global & DEFINED_BIT) {
- error(ERR_NONFATAL, "symbol `%s' redefined", label);
- return;
+ if ((lptr->defn.is_global & DEFINED_BIT) &&
+ (passn == 1 || !(lptr->defn.is_global & COMMON_BIT))) {
+ error(ERR_NONFATAL, "symbol `%s' redefined", label);
+ return;
}
- lptr->defn.is_global |= DEFINED_BIT;
+ lptr->defn.is_global |= DEFINED_BIT|COMMON_BIT;
- if (!islocalchar(label[0])) /* not local, but not special either */
+ if (!islocalchar(label[0])) {
prevlabel = lptr->defn.label;
- else
+ } else {
error(ERR_NONFATAL, "attempt to define a local label as a "
"common variable");
+ return;
+ }
lptr->defn.segment = segment;
lptr->defn.offset = 0;
+ if (pass0 == 0)
+ return;
+
ofmt->symdef(lptr->defn.label, segment, size, 2,
- special ? special : lptr->defn.special);
+ special ? special : lptr->defn.special);
ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2,
- special ? special : lptr->defn.
- special);
+ special ? special : lptr->defn.
+ special);
}
void declare_as_global(char *label, char *special, efunc error)