labels.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2018 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * labels.c label handling for the Netwide Assembler
  35. */
  36. #include "compiler.h"
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include "nasm.h"
  41. #include "nasmlib.h"
  42. #include "error.h"
  43. #include "hashtbl.h"
  44. #include "labels.h"
  45. /*
  46. * A dot-local label is one that begins with exactly one period. Things
  47. * that begin with _two_ periods are NASM-specific things.
  48. *
  49. * If TASM compatibility is enabled, a local label can also begin with
  50. * @@.
  51. */
  52. static bool islocal(const char *l)
  53. {
  54. if (tasm_compatible_mode) {
  55. if (l[0] == '@' && l[1] == '@')
  56. return true;
  57. }
  58. return (l[0] == '.' && l[1] != '.');
  59. }
  60. /*
  61. * Return true if this falls into NASM's '..' namespace
  62. */
  63. static bool ismagic(const char *l)
  64. {
  65. return l[0] == '.' && l[1] == '.' && l[2] != '@';
  66. }
  67. /*
  68. * Return true if we should update the local label base
  69. * as a result of this symbol. We must exclude local labels
  70. * as well as any kind of special labels, including ..@ ones.
  71. */
  72. static bool set_prevlabel(const char *l)
  73. {
  74. if (tasm_compatible_mode) {
  75. if (l[0] == '@' && l[1] == '@')
  76. return false;
  77. }
  78. return l[0] != '.';
  79. }
  80. #define LABEL_BLOCK 128 /* no. of labels/block */
  81. #define LBLK_SIZE (LABEL_BLOCK * sizeof(union label))
  82. #define END_LIST -3 /* don't clash with NO_SEG! */
  83. #define END_BLOCK -2
  84. #define PERMTS_SIZE 16384 /* size of text blocks */
  85. #if (PERMTS_SIZE < IDLEN_MAX)
  86. #error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX"
  87. #endif
  88. /* string values for enum label_type */
  89. static const char * const types[] =
  90. {"local", "global", "static", "extern", "common", "special",
  91. "output format special"};
  92. union label { /* actual label structures */
  93. struct {
  94. int32_t segment;
  95. int32_t subsection; /* Available for ofmt->herelabel() */
  96. int64_t offset;
  97. int64_t size;
  98. int64_t defined; /* 0 if undefined, passn+1 for when defn seen */
  99. char *label, *mangled, *special;
  100. const char *def_file; /* Where defined */
  101. int32_t def_line;
  102. enum label_type type, mangled_type;
  103. } defn;
  104. struct {
  105. int32_t movingon;
  106. int64_t dummy;
  107. union label *next;
  108. } admin;
  109. };
  110. struct permts { /* permanent text storage */
  111. struct permts *next; /* for the linked list */
  112. unsigned int size, usage; /* size and used space in ... */
  113. char data[PERMTS_SIZE]; /* ... the data block itself */
  114. };
  115. #define PERMTS_HEADER offsetof(struct permts, data)
  116. uint64_t global_offset_changed; /* counter for global offset changes */
  117. static struct hash_table ltab; /* labels hash table */
  118. static union label *ldata; /* all label data blocks */
  119. static union label *lfree; /* labels free block */
  120. static struct permts *perm_head; /* start of perm. text storage */
  121. static struct permts *perm_tail; /* end of perm. text storage */
  122. static void init_block(union label *blk);
  123. static char *perm_alloc(size_t len);
  124. static char *perm_copy(const char *string);
  125. static char *perm_copy3(const char *s1, const char *s2, const char *s3);
  126. static const char *mangle_label_name(union label *lptr);
  127. static const char *prevlabel;
  128. static bool initialized = false;
  129. /*
  130. * Emit a symdef to the output and the debug format backends.
  131. */
  132. static void out_symdef(union label *lptr)
  133. {
  134. int backend_type;
  135. int64_t backend_offset;
  136. /* Backend-defined special segments are passed to symdef immediately */
  137. if (pass0 == 2) {
  138. /* Emit special fixups for globals and commons */
  139. switch (lptr->defn.type) {
  140. case LBL_GLOBAL:
  141. case LBL_EXTERN:
  142. case LBL_COMMON:
  143. if (lptr->defn.special)
  144. ofmt->symdef(lptr->defn.mangled, 0, 0, 3, lptr->defn.special);
  145. break;
  146. default:
  147. break;
  148. }
  149. return;
  150. }
  151. if (pass0 != 1 && lptr->defn.type != LBL_BACKEND)
  152. return;
  153. /* Clean up this hack... */
  154. switch(lptr->defn.type) {
  155. case LBL_GLOBAL:
  156. case LBL_EXTERN:
  157. backend_type = 1;
  158. backend_offset = lptr->defn.offset;
  159. break;
  160. case LBL_COMMON:
  161. backend_type = 2;
  162. backend_offset = lptr->defn.size;
  163. break;
  164. default:
  165. backend_type = 0;
  166. backend_offset = lptr->defn.offset;
  167. break;
  168. }
  169. /* Might be necessary for a backend symbol */
  170. mangle_label_name(lptr);
  171. ofmt->symdef(lptr->defn.mangled, lptr->defn.segment,
  172. backend_offset, backend_type,
  173. lptr->defn.special);
  174. /*
  175. * NASM special symbols are not passed to the debug format; none
  176. * of the current backends want to see them.
  177. */
  178. if (lptr->defn.type == LBL_SPECIAL || lptr->defn.type == LBL_BACKEND)
  179. return;
  180. dfmt->debug_deflabel(lptr->defn.mangled, lptr->defn.segment,
  181. lptr->defn.offset, backend_type,
  182. lptr->defn.special);
  183. }
  184. /*
  185. * Internal routine: finds the `union label' corresponding to the
  186. * given label name. Creates a new one, if it isn't found, and if
  187. * `create' is true.
  188. */
  189. static union label *find_label(const char *label, bool create, bool *created)
  190. {
  191. union label *lptr, **lpp;
  192. char *label_str = NULL;
  193. struct hash_insert ip;
  194. nasm_assert(label != NULL);
  195. if (islocal(label))
  196. label = label_str = nasm_strcat(prevlabel, label);
  197. lpp = (union label **) hash_find(&ltab, label, &ip);
  198. lptr = lpp ? *lpp : NULL;
  199. if (lptr || !create) {
  200. if (created)
  201. *created = false;
  202. return lptr;
  203. }
  204. /* Create a new label... */
  205. if (lfree->admin.movingon == END_BLOCK) {
  206. /*
  207. * must allocate a new block
  208. */
  209. lfree->admin.next = nasm_malloc(LBLK_SIZE);
  210. lfree = lfree->admin.next;
  211. init_block(lfree);
  212. }
  213. if (created)
  214. *created = true;
  215. nasm_zero(*lfree);
  216. lfree->defn.label = perm_copy(label);
  217. lfree->defn.subsection = NO_SEG;
  218. if (label_str)
  219. nasm_free(label_str);
  220. hash_add(&ip, lfree->defn.label, lfree);
  221. return lfree++;
  222. }
  223. bool lookup_label(const char *label, int32_t *segment, int64_t *offset)
  224. {
  225. union label *lptr;
  226. if (!initialized)
  227. return false;
  228. lptr = find_label(label, false, NULL);
  229. if (lptr && lptr->defn.defined) {
  230. *segment = lptr->defn.segment;
  231. *offset = lptr->defn.offset;
  232. return true;
  233. }
  234. return false;
  235. }
  236. bool is_extern(const char *label)
  237. {
  238. union label *lptr;
  239. if (!initialized)
  240. return false;
  241. lptr = find_label(label, false, NULL);
  242. return lptr && lptr->defn.type == LBL_EXTERN;
  243. }
  244. static const char *mangle_strings[] = {"", "", "", ""};
  245. static bool mangle_string_set[ARRAY_SIZE(mangle_strings)];
  246. /*
  247. * Set a prefix or suffix
  248. */
  249. void set_label_mangle(enum mangle_index which, const char *what)
  250. {
  251. if (mangle_string_set[which])
  252. return; /* Once set, do not change */
  253. mangle_strings[which] = perm_copy(what);
  254. mangle_string_set[which] = true;
  255. }
  256. /*
  257. * Format a label name with appropriate prefixes and suffixes
  258. */
  259. static const char *mangle_label_name(union label *lptr)
  260. {
  261. const char *prefix;
  262. const char *suffix;
  263. if (likely(lptr->defn.mangled &&
  264. lptr->defn.mangled_type == lptr->defn.type))
  265. return lptr->defn.mangled; /* Already mangled */
  266. switch (lptr->defn.type) {
  267. case LBL_GLOBAL:
  268. case LBL_STATIC:
  269. case LBL_EXTERN:
  270. prefix = mangle_strings[LM_GPREFIX];
  271. suffix = mangle_strings[LM_GSUFFIX];
  272. break;
  273. case LBL_BACKEND:
  274. case LBL_SPECIAL:
  275. prefix = suffix = "";
  276. break;
  277. default:
  278. prefix = mangle_strings[LM_LPREFIX];
  279. suffix = mangle_strings[LM_LSUFFIX];
  280. break;
  281. }
  282. lptr->defn.mangled_type = lptr->defn.type;
  283. if (!(*prefix) && !(*suffix))
  284. lptr->defn.mangled = lptr->defn.label;
  285. else
  286. lptr->defn.mangled = perm_copy3(prefix, lptr->defn.label, suffix);
  287. return lptr->defn.mangled;
  288. }
  289. static void
  290. handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset)
  291. {
  292. int32_t oldseg;
  293. if (likely(!ofmt->herelabel))
  294. return;
  295. if (unlikely(location.segment == NO_SEG))
  296. return;
  297. oldseg = *segment;
  298. if (oldseg == location.segment && *offset == location.offset) {
  299. /* This label is defined at this location */
  300. int32_t newseg;
  301. bool copyoffset = false;
  302. nasm_assert(lptr->defn.mangled);
  303. newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type,
  304. oldseg, &lptr->defn.subsection, &copyoffset);
  305. if (likely(newseg == oldseg))
  306. return;
  307. *segment = newseg;
  308. if (copyoffset) {
  309. /* Maintain the offset from the old to the new segment */
  310. switch_segment(newseg);
  311. location.offset = *offset;
  312. } else {
  313. /* Keep a separate offset for the new segment */
  314. *offset = switch_segment(newseg);
  315. }
  316. }
  317. }
  318. static bool declare_label_lptr(union label *lptr,
  319. enum label_type type, const char *special)
  320. {
  321. if (special && !special[0])
  322. special = NULL;
  323. if (lptr->defn.type == type ||
  324. (pass0 == 0 && lptr->defn.type == LBL_LOCAL)) {
  325. lptr->defn.type = type;
  326. if (special) {
  327. if (!lptr->defn.special)
  328. lptr->defn.special = perm_copy(special);
  329. else if (nasm_stricmp(lptr->defn.special, special))
  330. nasm_error(ERR_NONFATAL,
  331. "symbol `%s' has inconsistent attributes `%s' and `%s'",
  332. lptr->defn.label, lptr->defn.special, special);
  333. }
  334. return true;
  335. }
  336. /* EXTERN can be replaced with GLOBAL or COMMON */
  337. if (lptr->defn.type == LBL_EXTERN &&
  338. (type == LBL_GLOBAL || type == LBL_COMMON)) {
  339. lptr->defn.type = type;
  340. /* Override special unconditionally */
  341. if (special)
  342. lptr->defn.special = perm_copy(special);
  343. return true;
  344. }
  345. /* GLOBAL or COMMON ignore subsequent EXTERN */
  346. if ((lptr->defn.type == LBL_GLOBAL || lptr->defn.type == LBL_COMMON) &&
  347. type == LBL_EXTERN) {
  348. if (!lptr->defn.special)
  349. lptr->defn.special = perm_copy(special);
  350. return false; /* Don't call define_label() after this! */
  351. }
  352. nasm_error(ERR_NONFATAL, "symbol `%s' declared both as %s and %s",
  353. lptr->defn.label, types[lptr->defn.type], types[type]);
  354. return false;
  355. }
  356. bool declare_label(const char *label, enum label_type type, const char *special)
  357. {
  358. union label *lptr = find_label(label, true, NULL);
  359. return declare_label_lptr(lptr, type, special);
  360. }
  361. /*
  362. * The "normal" argument decides if we should update the local segment
  363. * base name or not.
  364. */
  365. void define_label(const char *label, int32_t segment,
  366. int64_t offset, bool normal)
  367. {
  368. union label *lptr;
  369. bool created, changed;
  370. int64_t size;
  371. int64_t lastdef;
  372. /*
  373. * The backend may invoke this before pass 1, so treat that as
  374. * a special "pass".
  375. */
  376. const int64_t lpass = passn + 1;
  377. /*
  378. * Phase errors here can be one of two types: a new label appears,
  379. * or the offset changes. Increment global_offset_changed when that
  380. * happens, to tell the assembler core to make another pass.
  381. */
  382. lptr = find_label(label, true, &created);
  383. lastdef = lptr->defn.defined;
  384. if (segment) {
  385. /* We are actually defining this label */
  386. if (lptr->defn.type == LBL_EXTERN) {
  387. /* auto-promote EXTERN to GLOBAL */
  388. lptr->defn.type = LBL_GLOBAL;
  389. lastdef = 0; /* We are "re-creating" this label */
  390. }
  391. } else {
  392. /* It's a pseudo-segment (extern, common) */
  393. segment = lptr->defn.segment ? lptr->defn.segment : seg_alloc();
  394. }
  395. if (lastdef || lptr->defn.type == LBL_BACKEND) {
  396. /*
  397. * We have seen this on at least one previous pass, or
  398. * potentially earlier in this same pass (in which case we
  399. * will probably error out further down.)
  400. */
  401. mangle_label_name(lptr);
  402. handle_herelabel(lptr, &segment, &offset);
  403. }
  404. if (ismagic(label) && lptr->defn.type == LBL_LOCAL)
  405. lptr->defn.type = LBL_SPECIAL;
  406. if (set_prevlabel(label) && normal)
  407. prevlabel = lptr->defn.label;
  408. if (lptr->defn.type == LBL_COMMON) {
  409. size = offset;
  410. offset = 0;
  411. } else {
  412. size = 0; /* This is a hack... */
  413. }
  414. changed = created || !lastdef ||
  415. lptr->defn.segment != segment ||
  416. lptr->defn.offset != offset ||
  417. lptr->defn.size != size;
  418. global_offset_changed += changed;
  419. if (lastdef == lpass) {
  420. int32_t saved_line = 0;
  421. const char *saved_fname = NULL;
  422. int noteflags;
  423. /*
  424. * Defined elsewhere in the program, seen in this pass.
  425. */
  426. if (changed) {
  427. nasm_error(ERR_NONFATAL,
  428. "label `%s' inconsistently redefined",
  429. lptr->defn.label);
  430. noteflags = ERR_NOTE|ERR_HERE;
  431. } else {
  432. nasm_error(ERR_WARNING|WARN_LABEL_REDEF|ERR_PASS2,
  433. "label `%s' redefined to an identical value",
  434. lptr->defn.label);
  435. noteflags = ERR_NOTE|ERR_HERE|WARN_LABEL_REDEF|ERR_PASS2;
  436. }
  437. src_get(&saved_line, &saved_fname);
  438. src_set(lptr->defn.def_line, lptr->defn.def_file);
  439. nasm_error(noteflags, "label `%s' originally defined",
  440. lptr->defn.label);
  441. src_set(saved_line, saved_fname);
  442. } else if (changed && pass0 > 1 && lptr->defn.type != LBL_SPECIAL) {
  443. /*
  444. * WARN_LABEL_LATE defaults to an error, as this should never
  445. * actually happen. Just in case this is a backwards
  446. * compatibility problem, still make it a warning so that the
  447. * user can suppress or demote it.
  448. *
  449. * As a special case, LBL_SPECIAL symbols are allowed to be changed
  450. * even during the last pass.
  451. */
  452. nasm_error(ERR_WARNING|WARN_LABEL_LATE,
  453. "label `%s' %s during code generation",
  454. lptr->defn.label, created ? "defined" : "changed");
  455. }
  456. lptr->defn.segment = segment;
  457. lptr->defn.offset = offset;
  458. lptr->defn.size = size;
  459. lptr->defn.defined = lpass;
  460. if (changed || lastdef != lpass)
  461. src_get(&lptr->defn.def_line, &lptr->defn.def_file);
  462. if (lastdef != lpass)
  463. out_symdef(lptr);
  464. }
  465. /*
  466. * Define a special backend label
  467. */
  468. void backend_label(const char *label, int32_t segment, int64_t offset)
  469. {
  470. if (!declare_label(label, LBL_BACKEND, NULL))
  471. return;
  472. define_label(label, segment, offset, false);
  473. }
  474. int init_labels(void)
  475. {
  476. hash_init(&ltab, HASH_LARGE);
  477. ldata = lfree = nasm_malloc(LBLK_SIZE);
  478. init_block(lfree);
  479. perm_head = perm_tail =
  480. nasm_malloc(sizeof(struct permts));
  481. perm_head->next = NULL;
  482. perm_head->size = PERMTS_SIZE;
  483. perm_head->usage = 0;
  484. prevlabel = "";
  485. initialized = true;
  486. return 0;
  487. }
  488. void cleanup_labels(void)
  489. {
  490. union label *lptr, *lhold;
  491. initialized = false;
  492. hash_free(&ltab);
  493. lptr = lhold = ldata;
  494. while (lptr) {
  495. lptr = &lptr[LABEL_BLOCK-1];
  496. lptr = lptr->admin.next;
  497. nasm_free(lhold);
  498. lhold = lptr;
  499. }
  500. while (perm_head) {
  501. perm_tail = perm_head;
  502. perm_head = perm_head->next;
  503. nasm_free(perm_tail);
  504. }
  505. }
  506. static void init_block(union label *blk)
  507. {
  508. int j;
  509. for (j = 0; j < LABEL_BLOCK - 1; j++)
  510. blk[j].admin.movingon = END_LIST;
  511. blk[LABEL_BLOCK - 1].admin.movingon = END_BLOCK;
  512. blk[LABEL_BLOCK - 1].admin.next = NULL;
  513. }
  514. static char * safe_alloc perm_alloc(size_t len)
  515. {
  516. char *p;
  517. if (perm_tail->size - perm_tail->usage < len) {
  518. size_t alloc_len = (len > PERMTS_SIZE) ? len : PERMTS_SIZE;
  519. perm_tail->next = nasm_malloc(PERMTS_HEADER + alloc_len);
  520. perm_tail = perm_tail->next;
  521. perm_tail->next = NULL;
  522. perm_tail->size = alloc_len;
  523. perm_tail->usage = 0;
  524. }
  525. p = perm_tail->data + perm_tail->usage;
  526. perm_tail->usage += len;
  527. return p;
  528. }
  529. static char *perm_copy(const char *string)
  530. {
  531. char *p;
  532. size_t len;
  533. if (!string)
  534. return NULL;
  535. len = strlen(string)+1; /* Include final NUL */
  536. p = perm_alloc(len);
  537. memcpy(p, string, len);
  538. return p;
  539. }
  540. static char *
  541. perm_copy3(const char *s1, const char *s2, const char *s3)
  542. {
  543. char *p;
  544. size_t l1 = strlen(s1);
  545. size_t l2 = strlen(s2);
  546. size_t l3 = strlen(s3)+1; /* Include final NUL */
  547. p = perm_alloc(l1+l2+l3);
  548. memcpy(p, s1, l1);
  549. memcpy(p+l1, s2, l2);
  550. memcpy(p+l1+l2, s3, l3);
  551. return p;
  552. }
  553. const char *local_scope(const char *label)
  554. {
  555. return islocal(label) ? prevlabel : "";
  556. }
  557. /*
  558. * Notes regarding bug involving redefinition of external segments.
  559. *
  560. * Up to and including v0.97, the following code didn't work. From 0.97
  561. * developers release 2 onwards, it will generate an error.
  562. *
  563. * EXTERN extlabel
  564. * newlabel EQU extlabel + 1
  565. *
  566. * The results of allowing this code through are that two import records
  567. * are generated, one for 'extlabel' and one for 'newlabel'.
  568. *
  569. * The reason for this is an inadequacy in the defined interface between
  570. * the label manager and the output formats. The problem lies in how the
  571. * output format driver tells that a label is an external label for which
  572. * a label import record must be produced. Most (all except bin?) produce
  573. * the record if the segment number of the label is not one of the internal
  574. * segments that the output driver is producing.
  575. *
  576. * A simple fix to this would be to make the output formats keep track of
  577. * which symbols they've produced import records for, and make them not
  578. * produce import records for segments that are already defined.
  579. *
  580. * The best way, which is slightly harder but reduces duplication of code
  581. * and should therefore make the entire system smaller and more stable is
  582. * to change the interface between assembler, define_label(), and
  583. * the output module. The changes that are needed are:
  584. *
  585. * The semantics of the 'isextern' flag passed to define_label() need
  586. * examining. This information may or may not tell us what we need to
  587. * know (ie should we be generating an import record at this point for this
  588. * label). If these aren't the semantics, the semantics should be changed
  589. * to this.
  590. *
  591. * The output module interface needs changing, so that the `isextern' flag
  592. * is passed to the module, so that it can be easily tested for.
  593. */