section.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585
  1. /*
  2. * Section utility functions
  3. *
  4. * Copyright (C) 2001-2007 Peter Johnson
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
  19. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "util.h"
  28. #include <limits.h>
  29. #include "libyasm-stdint.h"
  30. #include "coretype.h"
  31. #include "hamt.h"
  32. #include "valparam.h"
  33. #include "assocdat.h"
  34. #include "linemap.h"
  35. #include "errwarn.h"
  36. #include "intnum.h"
  37. #include "expr.h"
  38. #include "value.h"
  39. #include "symrec.h"
  40. #include "bytecode.h"
  41. #include "arch.h"
  42. #include "section.h"
  43. #include "dbgfmt.h"
  44. #include "objfmt.h"
  45. #include "inttree.h"
  46. struct yasm_section {
  47. /*@reldef@*/ STAILQ_ENTRY(yasm_section) link;
  48. /*@dependent@*/ yasm_object *object; /* Pointer to parent object */
  49. /*@owned@*/ char *name; /* strdup()'ed name (given by user) */
  50. /* associated data; NULL if none */
  51. /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
  52. unsigned long align; /* Section alignment */
  53. unsigned long opt_flags; /* storage for optimizer flags */
  54. int code; /* section contains code (instructions) */
  55. int res_only; /* allow only resb family of bytecodes? */
  56. int def; /* "default" section, e.g. not specified by
  57. using section directive */
  58. /* the bytecodes for the section's contents */
  59. /*@reldef@*/ STAILQ_HEAD(yasm_bytecodehead, yasm_bytecode) bcs;
  60. /* the relocations for the section */
  61. /*@reldef@*/ STAILQ_HEAD(yasm_relochead, yasm_reloc) relocs;
  62. void (*destroy_reloc) (/*@only@*/ void *reloc);
  63. };
  64. static void yasm_section_destroy(/*@only@*/ yasm_section *sect);
  65. /* Wrapper around directive for HAMT insertion */
  66. typedef struct yasm_directive_wrap {
  67. const yasm_directive *directive;
  68. } yasm_directive_wrap;
  69. /*
  70. * Standard "builtin" object directives.
  71. */
  72. static void
  73. dir_extern(yasm_object *object, yasm_valparamhead *valparams,
  74. yasm_valparamhead *objext_valparams, unsigned long line)
  75. {
  76. yasm_valparam *vp = yasm_vps_first(valparams);
  77. yasm_symrec *sym;
  78. sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_EXTERN,
  79. line);
  80. if (objext_valparams) {
  81. yasm_valparamhead *vps = yasm_vps_create();
  82. *vps = *objext_valparams; /* structure copy */
  83. yasm_vps_initialize(objext_valparams); /* don't double-free */
  84. yasm_symrec_set_objext_valparams(sym, vps);
  85. }
  86. }
  87. static void
  88. dir_global(yasm_object *object, yasm_valparamhead *valparams,
  89. yasm_valparamhead *objext_valparams, unsigned long line)
  90. {
  91. yasm_valparam *vp = yasm_vps_first(valparams);
  92. yasm_symrec *sym;
  93. sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_GLOBAL,
  94. line);
  95. if (objext_valparams) {
  96. yasm_valparamhead *vps = yasm_vps_create();
  97. *vps = *objext_valparams; /* structure copy */
  98. yasm_vps_initialize(objext_valparams); /* don't double-free */
  99. yasm_symrec_set_objext_valparams(sym, vps);
  100. }
  101. }
  102. static void
  103. dir_common(yasm_object *object, yasm_valparamhead *valparams,
  104. yasm_valparamhead *objext_valparams, unsigned long line)
  105. {
  106. yasm_valparam *vp = yasm_vps_first(valparams);
  107. yasm_valparam *vp2 = yasm_vps_next(vp);
  108. yasm_expr *size = yasm_vp_expr(vp2, object->symtab, line);
  109. yasm_symrec *sym;
  110. if (!size) {
  111. yasm_error_set(YASM_ERROR_SYNTAX,
  112. N_("no size specified in %s declaration"), "COMMON");
  113. return;
  114. }
  115. sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_COMMON,
  116. line);
  117. yasm_symrec_set_common_size(sym, size);
  118. if (objext_valparams) {
  119. yasm_valparamhead *vps = yasm_vps_create();
  120. *vps = *objext_valparams; /* structure copy */
  121. yasm_vps_initialize(objext_valparams); /* don't double-free */
  122. yasm_symrec_set_objext_valparams(sym, vps);
  123. }
  124. }
  125. static void
  126. dir_section(yasm_object *object, yasm_valparamhead *valparams,
  127. yasm_valparamhead *objext_valparams, unsigned long line)
  128. {
  129. yasm_section *new_section =
  130. yasm_objfmt_section_switch(object, valparams, objext_valparams, line);
  131. if (new_section)
  132. object->cur_section = new_section;
  133. else
  134. yasm_error_set(YASM_ERROR_SYNTAX,
  135. N_("invalid argument to directive `%s'"), "SECTION");
  136. }
  137. static const yasm_directive object_directives[] = {
  138. { ".extern", "gas", dir_extern, YASM_DIR_ID_REQUIRED },
  139. { ".global", "gas", dir_global, YASM_DIR_ID_REQUIRED },
  140. { ".globl", "gas", dir_global, YASM_DIR_ID_REQUIRED },
  141. { "extern", "nasm", dir_extern, YASM_DIR_ID_REQUIRED },
  142. { "global", "nasm", dir_global, YASM_DIR_ID_REQUIRED },
  143. { "common", "nasm", dir_common, YASM_DIR_ID_REQUIRED },
  144. { "section", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
  145. { "segment", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
  146. { NULL, NULL, NULL, 0 }
  147. };
  148. static void
  149. directive_level2_delete(/*@only@*/ void *data)
  150. {
  151. yasm_xfree(data);
  152. }
  153. static void
  154. directive_level1_delete(/*@only@*/ void *data)
  155. {
  156. HAMT_destroy(data, directive_level2_delete);
  157. }
  158. static void
  159. directives_add(yasm_object *object, /*@null@*/ const yasm_directive *dir)
  160. {
  161. if (!dir)
  162. return;
  163. while (dir->name) {
  164. HAMT *level2 = HAMT_search(object->directives, dir->parser);
  165. int replace;
  166. yasm_directive_wrap *wrap = yasm_xmalloc(sizeof(yasm_directive_wrap));
  167. if (!level2) {
  168. replace = 0;
  169. level2 = HAMT_insert(object->directives, dir->parser,
  170. HAMT_create(1, yasm_internal_error_),
  171. &replace, directive_level1_delete);
  172. }
  173. replace = 0;
  174. wrap->directive = dir;
  175. HAMT_insert(level2, dir->name, wrap, &replace,
  176. directive_level2_delete);
  177. dir++;
  178. }
  179. }
  180. /*@-compdestroy@*/
  181. yasm_object *
  182. yasm_object_create(const char *src_filename, const char *obj_filename,
  183. /*@kept@*/ yasm_arch *arch,
  184. const yasm_objfmt_module *objfmt_module,
  185. const yasm_dbgfmt_module *dbgfmt_module)
  186. {
  187. yasm_object *object = yasm_xmalloc(sizeof(yasm_object));
  188. int matched, i;
  189. object->src_filename = yasm__xstrdup(src_filename);
  190. object->deb_filename = NULL;
  191. object->obj_filename = yasm__xstrdup(obj_filename);
  192. /* No prefix/suffix */
  193. object->global_prefix = yasm__xstrdup("");
  194. object->global_suffix = yasm__xstrdup("");
  195. /* Create empty symbol table */
  196. object->symtab = yasm_symtab_create();
  197. /* Initialize sections linked list */
  198. STAILQ_INIT(&object->sections);
  199. /* Create directives HAMT */
  200. object->directives = HAMT_create(1, yasm_internal_error_);
  201. /* Initialize the target architecture */
  202. object->arch = arch;
  203. /* Initialize things to NULL in case of error */
  204. object->dbgfmt = NULL;
  205. /* Initialize the object format */
  206. object->objfmt = yasm_objfmt_create(objfmt_module, object);
  207. if (!object->objfmt) {
  208. yasm_error_set(YASM_ERROR_GENERAL,
  209. N_("object format `%s' does not support architecture `%s' machine `%s'"),
  210. objfmt_module->keyword, ((yasm_arch_base *)arch)->module->keyword,
  211. yasm_arch_get_machine(arch));
  212. goto error;
  213. }
  214. /* Get a fresh copy of objfmt_module as it may have changed. */
  215. objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
  216. /* Add an initial "default" section to object */
  217. object->cur_section = yasm_objfmt_add_default_section(object);
  218. /* Check to see if the requested debug format is in the allowed list
  219. * for the active object format.
  220. */
  221. matched = 0;
  222. for (i=0; objfmt_module->dbgfmt_keywords[i]; i++) {
  223. if (yasm__strcasecmp(objfmt_module->dbgfmt_keywords[i],
  224. dbgfmt_module->keyword) == 0) {
  225. matched = 1;
  226. break;
  227. }
  228. }
  229. if (!matched) {
  230. yasm_error_set(YASM_ERROR_GENERAL,
  231. N_("`%s' is not a valid debug format for object format `%s'"),
  232. dbgfmt_module->keyword, objfmt_module->keyword);
  233. goto error;
  234. }
  235. /* Initialize the debug format */
  236. object->dbgfmt = yasm_dbgfmt_create(dbgfmt_module, object);
  237. if (!object->dbgfmt) {
  238. yasm_error_set(YASM_ERROR_GENERAL,
  239. N_("debug format `%s' does not work with object format `%s'"),
  240. dbgfmt_module->keyword, objfmt_module->keyword);
  241. goto error;
  242. }
  243. /* Add directives to HAMT. Note ordering here determines priority. */
  244. directives_add(object,
  245. ((yasm_objfmt_base *)object->objfmt)->module->directives);
  246. directives_add(object,
  247. ((yasm_dbgfmt_base *)object->dbgfmt)->module->directives);
  248. directives_add(object,
  249. ((yasm_arch_base *)object->arch)->module->directives);
  250. directives_add(object, object_directives);
  251. return object;
  252. error:
  253. yasm_object_destroy(object);
  254. return NULL;
  255. }
  256. /*@=compdestroy@*/
  257. /*@-onlytrans@*/
  258. yasm_section *
  259. yasm_object_get_general(yasm_object *object, const char *name,
  260. unsigned long align, int code, int res_only,
  261. int *isnew, unsigned long line)
  262. {
  263. yasm_section *s;
  264. yasm_bytecode *bc;
  265. /* Search through current sections to see if we already have one with
  266. * that name.
  267. */
  268. STAILQ_FOREACH(s, &object->sections, link) {
  269. if (strcmp(s->name, name) == 0) {
  270. *isnew = 0;
  271. return s;
  272. }
  273. }
  274. /* No: we have to allocate and create a new one. */
  275. /* Okay, the name is valid; now allocate and initialize */
  276. s = yasm_xcalloc(1, sizeof(yasm_section));
  277. STAILQ_INSERT_TAIL(&object->sections, s, link);
  278. s->object = object;
  279. s->name = yasm__xstrdup(name);
  280. s->assoc_data = NULL;
  281. s->align = align;
  282. /* Initialize bytecodes with one empty bytecode (acts as "prior" for first
  283. * real bytecode in section.
  284. */
  285. STAILQ_INIT(&s->bcs);
  286. bc = yasm_bc_create_common(NULL, NULL, 0);
  287. bc->section = s;
  288. bc->offset = 0;
  289. STAILQ_INSERT_TAIL(&s->bcs, bc, link);
  290. /* Initialize relocs */
  291. STAILQ_INIT(&s->relocs);
  292. s->destroy_reloc = NULL;
  293. s->code = code;
  294. s->res_only = res_only;
  295. s->def = 0;
  296. /* Initialize object format specific data */
  297. yasm_objfmt_init_new_section(s, line);
  298. *isnew = 1;
  299. return s;
  300. }
  301. /*@=onlytrans@*/
  302. int
  303. yasm_object_directive(yasm_object *object, const char *name,
  304. const char *parser, yasm_valparamhead *valparams,
  305. yasm_valparamhead *objext_valparams,
  306. unsigned long line)
  307. {
  308. HAMT *level2;
  309. yasm_directive_wrap *wrap;
  310. level2 = HAMT_search(object->directives, parser);
  311. if (!level2)
  312. return 1;
  313. wrap = HAMT_search(level2, name);
  314. if (!wrap)
  315. return 1;
  316. yasm_call_directive(wrap->directive, object, valparams, objext_valparams,
  317. line);
  318. return 0;
  319. }
  320. void
  321. yasm_object_set_source_fn(yasm_object *object, const char *src_filename)
  322. {
  323. yasm_xfree(object->src_filename);
  324. object->src_filename = yasm__xstrdup(src_filename);
  325. yasm_xfree(object->deb_filename);
  326. object->deb_filename = NULL;
  327. }
  328. void
  329. yasm_object_set_global_prefix(yasm_object *object, const char *prefix)
  330. {
  331. yasm_xfree(object->global_prefix);
  332. object->global_prefix = yasm__xstrdup(prefix);
  333. }
  334. void
  335. yasm_object_set_global_suffix(yasm_object *object, const char *suffix)
  336. {
  337. yasm_xfree(object->global_suffix);
  338. object->global_suffix = yasm__xstrdup(suffix);
  339. }
  340. int
  341. yasm_section_is_code(yasm_section *sect)
  342. {
  343. return sect->code;
  344. }
  345. unsigned long
  346. yasm_section_get_opt_flags(const yasm_section *sect)
  347. {
  348. return sect->opt_flags;
  349. }
  350. void
  351. yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags)
  352. {
  353. sect->opt_flags = opt_flags;
  354. }
  355. int
  356. yasm_section_is_default(const yasm_section *sect)
  357. {
  358. return sect->def;
  359. }
  360. void
  361. yasm_section_set_default(yasm_section *sect, int def)
  362. {
  363. sect->def = def;
  364. }
  365. yasm_object *
  366. yasm_section_get_object(const yasm_section *sect)
  367. {
  368. return sect->object;
  369. }
  370. void *
  371. yasm_section_get_data(yasm_section *sect,
  372. const yasm_assoc_data_callback *callback)
  373. {
  374. return yasm__assoc_data_get(sect->assoc_data, callback);
  375. }
  376. void
  377. yasm_section_add_data(yasm_section *sect,
  378. const yasm_assoc_data_callback *callback, void *data)
  379. {
  380. sect->assoc_data = yasm__assoc_data_add(sect->assoc_data, callback, data);
  381. }
  382. void
  383. yasm_object_destroy(yasm_object *object)
  384. {
  385. yasm_section *cur, *next;
  386. /* Delete object format, debug format, and arch. This can be called
  387. * due to an error in yasm_object_create(), so look out for NULLs.
  388. */
  389. if (object->objfmt)
  390. yasm_objfmt_destroy(object->objfmt);
  391. if (object->dbgfmt)
  392. yasm_dbgfmt_destroy(object->dbgfmt);
  393. /* Delete sections */
  394. cur = STAILQ_FIRST(&object->sections);
  395. while (cur) {
  396. next = STAILQ_NEXT(cur, link);
  397. yasm_section_destroy(cur);
  398. cur = next;
  399. }
  400. /* Delete directives HAMT */
  401. HAMT_destroy(object->directives, directive_level1_delete);
  402. /* Delete prefix/suffix */
  403. yasm_xfree(object->global_prefix);
  404. yasm_xfree(object->global_suffix);
  405. /* Delete associated filenames */
  406. yasm_xfree(object->src_filename);
  407. yasm_xfree(object->deb_filename);
  408. yasm_xfree(object->obj_filename);
  409. /* Delete symbol table */
  410. yasm_symtab_destroy(object->symtab);
  411. /* Delete architecture */
  412. if (object->arch)
  413. yasm_arch_destroy(object->arch);
  414. yasm_xfree(object);
  415. }
  416. void
  417. yasm_object_print(const yasm_object *object, FILE *f, int indent_level)
  418. {
  419. yasm_section *cur;
  420. /* Print symbol table */
  421. fprintf(f, "%*sSymbol Table:\n", indent_level, "");
  422. yasm_symtab_print(object->symtab, f, indent_level+1);
  423. /* Print sections and bytecodes */
  424. STAILQ_FOREACH(cur, &object->sections, link) {
  425. fprintf(f, "%*sSection:\n", indent_level, "");
  426. yasm_section_print(cur, f, indent_level+1, 1);
  427. }
  428. }
  429. void
  430. yasm_object_finalize(yasm_object *object, yasm_errwarns *errwarns)
  431. {
  432. yasm_section *sect;
  433. /* Iterate through sections */
  434. STAILQ_FOREACH(sect, &object->sections, link) {
  435. yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
  436. yasm_bytecode *prev;
  437. /* Skip our locally created empty bytecode first. */
  438. prev = cur;
  439. cur = STAILQ_NEXT(cur, link);
  440. /* Iterate through the remainder, if any. */
  441. while (cur) {
  442. /* Finalize */
  443. yasm_bc_finalize(cur, prev);
  444. yasm_errwarn_propagate(errwarns, cur->line);
  445. prev = cur;
  446. cur = STAILQ_NEXT(cur, link);
  447. }
  448. }
  449. }
  450. int
  451. yasm_object_sections_traverse(yasm_object *object, /*@null@*/ void *d,
  452. int (*func) (yasm_section *sect,
  453. /*@null@*/ void *d))
  454. {
  455. yasm_section *cur;
  456. STAILQ_FOREACH(cur, &object->sections, link) {
  457. int retval = func(cur, d);
  458. if (retval != 0)
  459. return retval;
  460. }
  461. return 0;
  462. }
  463. /*@-onlytrans@*/
  464. yasm_section *
  465. yasm_object_find_general(yasm_object *object, const char *name)
  466. {
  467. yasm_section *cur;
  468. STAILQ_FOREACH(cur, &object->sections, link) {
  469. if (strcmp(cur->name, name) == 0)
  470. return cur;
  471. }
  472. return NULL;
  473. }
  474. /*@=onlytrans@*/
  475. void
  476. yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
  477. void (*destroy_func) (/*@only@*/ void *reloc))
  478. {
  479. STAILQ_INSERT_TAIL(&sect->relocs, reloc, link);
  480. if (!destroy_func)
  481. yasm_internal_error(N_("NULL destroy function given to add_reloc"));
  482. else if (sect->destroy_reloc && destroy_func != sect->destroy_reloc)
  483. yasm_internal_error(N_("different destroy function given to add_reloc"));
  484. sect->destroy_reloc = destroy_func;
  485. }
  486. /*@null@*/ yasm_reloc *
  487. yasm_section_relocs_first(yasm_section *sect)
  488. {
  489. return STAILQ_FIRST(&sect->relocs);
  490. }
  491. #undef yasm_section_reloc_next
  492. /*@null@*/ yasm_reloc *
  493. yasm_section_reloc_next(yasm_reloc *reloc)
  494. {
  495. return STAILQ_NEXT(reloc, link);
  496. }
  497. void
  498. yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp, yasm_symrec **symp)
  499. {
  500. *addrp = reloc->addr;
  501. *symp = reloc->sym;
  502. }
  503. yasm_bytecode *
  504. yasm_section_bcs_first(yasm_section *sect)
  505. {
  506. return STAILQ_FIRST(&sect->bcs);
  507. }
  508. yasm_bytecode *
  509. yasm_section_bcs_last(yasm_section *sect)
  510. {
  511. return STAILQ_LAST(&sect->bcs, yasm_bytecode, link);
  512. }
  513. yasm_bytecode *
  514. yasm_section_bcs_append(yasm_section *sect, yasm_bytecode *bc)
  515. {
  516. if (bc) {
  517. if (bc->callback) {
  518. bc->section = sect; /* record parent section */
  519. STAILQ_INSERT_TAIL(&sect->bcs, bc, link);
  520. return bc;
  521. } else
  522. yasm_xfree(bc);
  523. }
  524. return (yasm_bytecode *)NULL;
  525. }
  526. int
  527. yasm_section_bcs_traverse(yasm_section *sect,
  528. /*@null@*/ yasm_errwarns *errwarns,
  529. /*@null@*/ void *d,
  530. int (*func) (yasm_bytecode *bc, /*@null@*/ void *d))
  531. {
  532. yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
  533. /* Skip our locally created empty bytecode first. */
  534. cur = STAILQ_NEXT(cur, link);
  535. /* Iterate through the remainder, if any. */
  536. while (cur) {
  537. int retval = func(cur, d);
  538. if (errwarns)
  539. yasm_errwarn_propagate(errwarns, cur->line);
  540. if (retval != 0)
  541. return retval;
  542. cur = STAILQ_NEXT(cur, link);
  543. }
  544. return 0;
  545. }
  546. const char *
  547. yasm_section_get_name(const yasm_section *sect)
  548. {
  549. return sect->name;
  550. }
  551. void
  552. yasm_section_set_align(yasm_section *sect, unsigned long align,
  553. unsigned long line)
  554. {
  555. sect->align = align;
  556. }
  557. unsigned long
  558. yasm_section_get_align(const yasm_section *sect)
  559. {
  560. return sect->align;
  561. }
  562. static void
  563. yasm_section_destroy(yasm_section *sect)
  564. {
  565. yasm_bytecode *cur, *next;
  566. yasm_reloc *r_cur, *r_next;
  567. if (!sect)
  568. return;
  569. yasm_xfree(sect->name);
  570. yasm__assoc_data_destroy(sect->assoc_data);
  571. /* Delete bytecodes */
  572. cur = STAILQ_FIRST(&sect->bcs);
  573. while (cur) {
  574. next = STAILQ_NEXT(cur, link);
  575. yasm_bc_destroy(cur);
  576. cur = next;
  577. }
  578. /* Delete relocations */
  579. r_cur = STAILQ_FIRST(&sect->relocs);
  580. while (r_cur) {
  581. r_next = STAILQ_NEXT(r_cur, link);
  582. yasm_intnum_destroy(r_cur->addr);
  583. sect->destroy_reloc(r_cur);
  584. r_cur = r_next;
  585. }
  586. yasm_xfree(sect);
  587. }
  588. void
  589. yasm_section_print(const yasm_section *sect, FILE *f, int indent_level,
  590. int print_bcs)
  591. {
  592. if (!sect) {
  593. fprintf(f, "%*s(none)\n", indent_level, "");
  594. return;
  595. }
  596. fprintf(f, "%*sname=%s\n", indent_level, "", sect->name);
  597. if (sect->assoc_data) {
  598. fprintf(f, "%*sAssociated data:\n", indent_level, "");
  599. yasm__assoc_data_print(sect->assoc_data, f, indent_level+1);
  600. }
  601. if (print_bcs) {
  602. yasm_bytecode *cur;
  603. fprintf(f, "%*sBytecodes:\n", indent_level, "");
  604. STAILQ_FOREACH(cur, &sect->bcs, link) {
  605. fprintf(f, "%*sNext Bytecode:\n", indent_level+1, "");
  606. yasm_bc_print(cur, f, indent_level+2);
  607. }
  608. }
  609. }
  610. /*
  611. * Robertson (1977) optimizer
  612. * Based (somewhat loosely) on the algorithm given in:
  613. * MRC Technical Summary Report # 1779
  614. * CODE GENERATION FOR SHORT/LONG ADDRESS MACHINES
  615. * Edward L. Robertson
  616. * Mathematics Research Center
  617. * University of Wisconsin-Madison
  618. * 610 Walnut Street
  619. * Madison, Wisconsin 53706
  620. * August 1977
  621. *
  622. * Key components of algorithm:
  623. * - start assuming all short forms
  624. * - build spans for short->long transition dependencies
  625. * - if a long form is needed, walk the dependencies and update
  626. * Major differences from Robertson's algorithm:
  627. * - detection of cycles
  628. * - any difference of two locations is allowed
  629. * - handling of alignment/org gaps (offset setting)
  630. * - handling of multiples
  631. *
  632. * Data structures:
  633. * - Interval tree to store spans and associated data
  634. * - Queues QA and QB
  635. *
  636. * Each span keeps track of:
  637. * - Associated bytecode (bytecode that depends on the span length)
  638. * - Active/inactive state (starts out active)
  639. * - Sign (negative/positive; negative being "backwards" in address)
  640. * - Current length in bytes
  641. * - New length in bytes
  642. * - Negative/Positive thresholds
  643. * - Span ID (unique within each bytecode)
  644. *
  645. * How org and align and any other offset-based bytecodes are handled:
  646. *
  647. * Some portions are critical values that must not depend on any bytecode
  648. * offset (either relative or absolute).
  649. *
  650. * All offset-setters (ORG and ALIGN) are put into a linked list in section
  651. * order (e.g. increasing offset order). Each span keeps track of the next
  652. * offset-setter following the span's associated bytecode.
  653. *
  654. * When a bytecode is expanded, the next offset-setter is examined. The
  655. * offset-setter may be able to absorb the expansion (e.g. any offset
  656. * following it would not change), or it may have to move forward (in the
  657. * case of align) or error (in the case of org). If it has to move forward,
  658. * following offset-setters must also be examined for absorption or moving
  659. * forward. In either case, the ongoing offset is updated as well as the
  660. * lengths of any spans dependent on the offset-setter.
  661. *
  662. * Alignment/ORG value is critical value.
  663. * Cannot be combined with TIMES.
  664. *
  665. * How times is handled:
  666. *
  667. * TIMES: Handled separately from bytecode "raw" size. If not span-dependent,
  668. * trivial (just multiplied in at any bytecode size increase). Span
  669. * dependent times update on any change (span ID 0). If the resultant
  670. * next bytecode offset would be less than the old next bytecode offset,
  671. * error. Otherwise increase offset and update dependent spans.
  672. *
  673. * To reduce interval tree size, a first expansion pass is performed
  674. * before the spans are added to the tree.
  675. *
  676. * Basic algorithm outline:
  677. *
  678. * 1. Initialization:
  679. * a. Number bytecodes sequentially (via bc_index) and calculate offsets
  680. * of all bytecodes assuming minimum length, building a list of all
  681. * dependent spans as we go.
  682. * "minimum" here means absolute minimum:
  683. * - align/org (offset-based) bumps offset as normal
  684. * - times values (with span-dependent values) assumed to be 0
  685. * b. Iterate over spans. Set span length based on bytecode offsets
  686. * determined in 1a. If span is "certainly" long because the span
  687. * is an absolute reference to another section (or external) or the
  688. * distance calculated based on the minimum length is greater than the
  689. * span's threshold, expand the span's bytecode, and if no further
  690. * expansion can result, mark span as inactive.
  691. * c. Iterate over bytecodes to update all bytecode offsets based on new
  692. * (expanded) lengths calculated in 1b.
  693. * d. Iterate over active spans. Add span to interval tree. Update span's
  694. * length based on new bytecode offsets determined in 1c. If span's
  695. * length exceeds long threshold, add that span to Q.
  696. * 2. Main loop:
  697. * While Q not empty:
  698. * Expand BC dependent on span at head of Q (and remove span from Q).
  699. * Update span:
  700. * If BC no longer dependent on span, mark span as inactive.
  701. * If BC has new thresholds for span, update span.
  702. * If BC increased in size, for each active span that contains BC:
  703. * Increase span length by difference between short and long BC length.
  704. * If span exceeds long threshold (or is flagged to recalculate on any
  705. * change), add it to tail of Q.
  706. * 3. Final pass over bytecodes to generate final offsets.
  707. */
  708. typedef struct yasm_span yasm_span;
  709. typedef struct yasm_offset_setter {
  710. /* Linked list in section order (e.g. offset order) */
  711. /*@reldef@*/ STAILQ_ENTRY(yasm_offset_setter) link;
  712. /*@dependent@*/ yasm_bytecode *bc;
  713. unsigned long cur_val, new_val;
  714. unsigned long thres;
  715. } yasm_offset_setter;
  716. typedef struct yasm_span_term {
  717. yasm_bytecode *precbc, *precbc2;
  718. yasm_span *span; /* span this term is a member of */
  719. long cur_val, new_val;
  720. unsigned int subst;
  721. } yasm_span_term;
  722. struct yasm_span {
  723. /*@reldef@*/ TAILQ_ENTRY(yasm_span) link; /* for allocation tracking */
  724. /*@reldef@*/ STAILQ_ENTRY(yasm_span) linkq; /* for Q */
  725. /*@dependent@*/ yasm_bytecode *bc;
  726. yasm_value depval;
  727. /* span term for relative portion of value */
  728. yasm_span_term *rel_term;
  729. /* span terms in absolute portion of value */
  730. yasm_span_term *terms;
  731. yasm_expr__item *items;
  732. unsigned int num_terms;
  733. long cur_val;
  734. long new_val;
  735. long neg_thres;
  736. long pos_thres;
  737. int id;
  738. int active;
  739. /* NULL-terminated array of spans that led to this span. Used only for
  740. * checking for circular references (cycles) with id=0 spans.
  741. */
  742. yasm_span **backtrace;
  743. int backtrace_size;
  744. /* First offset setter following this span's bytecode */
  745. yasm_offset_setter *os;
  746. };
  747. typedef struct optimize_data {
  748. /*@reldef@*/ TAILQ_HEAD(yasm_span_head, yasm_span) spans;
  749. /*@reldef@*/ STAILQ_HEAD(yasm_span_shead, yasm_span) QA, QB;
  750. /*@only@*/ IntervalTree *itree;
  751. /*@reldef@*/ STAILQ_HEAD(offset_setters_head, yasm_offset_setter)
  752. offset_setters;
  753. long len_diff; /* used only for optimize_term_expand */
  754. yasm_span *span; /* used only for check_cycle */
  755. yasm_offset_setter *os;
  756. } optimize_data;
  757. static yasm_span *
  758. create_span(yasm_bytecode *bc, int id, /*@null@*/ const yasm_value *value,
  759. long neg_thres, long pos_thres, yasm_offset_setter *os)
  760. {
  761. yasm_span *span = yasm_xmalloc(sizeof(yasm_span));
  762. span->bc = bc;
  763. if (value)
  764. yasm_value_init_copy(&span->depval, value);
  765. else
  766. yasm_value_initialize(&span->depval, NULL, 0);
  767. span->rel_term = NULL;
  768. span->terms = NULL;
  769. span->items = NULL;
  770. span->num_terms = 0;
  771. span->cur_val = 0;
  772. span->new_val = 0;
  773. span->neg_thres = neg_thres;
  774. span->pos_thres = pos_thres;
  775. span->id = id;
  776. span->active = 1;
  777. span->backtrace = NULL;
  778. span->backtrace_size = 0;
  779. span->os = os;
  780. return span;
  781. }
  782. static void
  783. optimize_add_span(void *add_span_data, yasm_bytecode *bc, int id,
  784. const yasm_value *value, long neg_thres, long pos_thres)
  785. {
  786. optimize_data *optd = (optimize_data *)add_span_data;
  787. yasm_span *span;
  788. span = create_span(bc, id, value, neg_thres, pos_thres, optd->os);
  789. TAILQ_INSERT_TAIL(&optd->spans, span, link);
  790. }
  791. static void
  792. add_span_term(unsigned int subst, yasm_bytecode *precbc,
  793. yasm_bytecode *precbc2, void *d)
  794. {
  795. yasm_span *span = d;
  796. yasm_intnum *intn;
  797. if (subst >= span->num_terms) {
  798. /* Linear expansion since total number is essentially always small */
  799. span->num_terms = subst+1;
  800. span->terms = yasm_xrealloc(span->terms,
  801. span->num_terms*sizeof(yasm_span_term));
  802. }
  803. span->terms[subst].precbc = precbc;
  804. span->terms[subst].precbc2 = precbc2;
  805. span->terms[subst].span = span;
  806. span->terms[subst].subst = subst;
  807. intn = yasm_calc_bc_dist(precbc, precbc2);
  808. if (!intn)
  809. yasm_internal_error(N_("could not calculate bc distance"));
  810. span->terms[subst].cur_val = 0;
  811. span->terms[subst].new_val = yasm_intnum_get_int(intn);
  812. yasm_intnum_destroy(intn);
  813. }
  814. static void
  815. span_create_terms(yasm_span *span)
  816. {
  817. unsigned int i;
  818. /* Split out sym-sym terms in absolute portion of dependent value */
  819. if (span->depval.abs) {
  820. span->num_terms = yasm_expr__bc_dist_subst(&span->depval.abs, span,
  821. add_span_term);
  822. if (span->num_terms > 0) {
  823. span->items = yasm_xmalloc(span->num_terms*sizeof(yasm_expr__item));
  824. for (i=0; i<span->num_terms; i++) {
  825. /* Create items with dummy value */
  826. span->items[i].type = YASM_EXPR_INT;
  827. span->items[i].data.intn = yasm_intnum_create_int(0);
  828. /* Check for circular references */
  829. if (span->id <= 0 &&
  830. ((span->bc->bc_index > span->terms[i].precbc->bc_index &&
  831. span->bc->bc_index <= span->terms[i].precbc2->bc_index) ||
  832. (span->bc->bc_index > span->terms[i].precbc2->bc_index &&
  833. span->bc->bc_index <= span->terms[i].precbc->bc_index)))
  834. yasm_error_set(YASM_ERROR_VALUE,
  835. N_("circular reference detected"));
  836. }
  837. }
  838. }
  839. /* Create term for relative portion of dependent value */
  840. if (span->depval.rel) {
  841. yasm_bytecode *rel_precbc;
  842. int sym_local;
  843. sym_local = yasm_symrec_get_label(span->depval.rel, &rel_precbc);
  844. if (span->depval.wrt || span->depval.seg_of || span->depval.section_rel
  845. || !sym_local)
  846. return; /* we can't handle SEG, WRT, or external symbols */
  847. if (rel_precbc->section != span->bc->section)
  848. return; /* not in this section */
  849. if (!span->depval.curpos_rel)
  850. return; /* not PC-relative */
  851. span->rel_term = yasm_xmalloc(sizeof(yasm_span_term));
  852. span->rel_term->precbc = NULL;
  853. span->rel_term->precbc2 = rel_precbc;
  854. span->rel_term->span = span;
  855. span->rel_term->subst = ~0U;
  856. span->rel_term->cur_val = 0;
  857. span->rel_term->new_val = yasm_bc_next_offset(rel_precbc) -
  858. span->bc->offset;
  859. }
  860. }
  861. /* Recalculate span value based on current span replacement values.
  862. * Returns 1 if span needs expansion (e.g. exceeded thresholds).
  863. */
  864. static int
  865. recalc_normal_span(yasm_span *span)
  866. {
  867. span->new_val = 0;
  868. if (span->depval.abs) {
  869. yasm_expr *abs_copy = yasm_expr_copy(span->depval.abs);
  870. /*@null@*/ /*@dependent@*/ yasm_intnum *num;
  871. /* Update sym-sym terms and substitute back into expr */
  872. unsigned int i;
  873. for (i=0; i<span->num_terms; i++)
  874. yasm_intnum_set_int(span->items[i].data.intn,
  875. span->terms[i].new_val);
  876. yasm_expr__subst(abs_copy, span->num_terms, span->items);
  877. num = yasm_expr_get_intnum(&abs_copy, 0);
  878. if (num)
  879. span->new_val = yasm_intnum_get_int(num);
  880. else
  881. span->new_val = LONG_MAX; /* too complex; force to longest form */
  882. yasm_expr_destroy(abs_copy);
  883. }
  884. if (span->rel_term) {
  885. if (span->new_val != LONG_MAX && span->rel_term->new_val != LONG_MAX)
  886. span->new_val += span->rel_term->new_val >> span->depval.rshift;
  887. else
  888. span->new_val = LONG_MAX; /* too complex; force to longest form */
  889. } else if (span->depval.rel)
  890. span->new_val = LONG_MAX; /* too complex; force to longest form */
  891. if (span->new_val == LONG_MAX)
  892. span->active = 0;
  893. /* If id<=0, flag update on any change */
  894. if (span->id <= 0)
  895. return (span->new_val != span->cur_val);
  896. return (span->new_val < span->neg_thres
  897. || span->new_val > span->pos_thres);
  898. }
  899. /* Updates all bytecode offsets. For offset-based bytecodes, calls expand
  900. * to determine new length.
  901. */
  902. static int
  903. update_all_bc_offsets(yasm_object *object, yasm_errwarns *errwarns)
  904. {
  905. yasm_section *sect;
  906. int saw_error = 0;
  907. STAILQ_FOREACH(sect, &object->sections, link) {
  908. unsigned long offset = 0;
  909. yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
  910. yasm_bytecode *prevbc;
  911. /* Skip our locally created empty bytecode first. */
  912. prevbc = bc;
  913. bc = STAILQ_NEXT(bc, link);
  914. /* Iterate through the remainder, if any. */
  915. while (bc) {
  916. if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
  917. /* Recalculate/adjust len of offset-based bytecodes here */
  918. long neg_thres = 0;
  919. long pos_thres = (long)yasm_bc_next_offset(bc);
  920. int retval = yasm_bc_expand(bc, 1, 0,
  921. (long)yasm_bc_next_offset(prevbc),
  922. &neg_thres, &pos_thres);
  923. yasm_errwarn_propagate(errwarns, bc->line);
  924. if (retval < 0)
  925. saw_error = 1;
  926. }
  927. bc->offset = offset;
  928. offset += bc->len*bc->mult_int;
  929. prevbc = bc;
  930. bc = STAILQ_NEXT(bc, link);
  931. }
  932. }
  933. return saw_error;
  934. }
  935. static void
  936. span_destroy(/*@only@*/ yasm_span *span)
  937. {
  938. unsigned int i;
  939. yasm_value_delete(&span->depval);
  940. if (span->rel_term)
  941. yasm_xfree(span->rel_term);
  942. if (span->terms)
  943. yasm_xfree(span->terms);
  944. if (span->items) {
  945. for (i=0; i<span->num_terms; i++)
  946. yasm_intnum_destroy(span->items[i].data.intn);
  947. yasm_xfree(span->items);
  948. }
  949. if (span->backtrace)
  950. yasm_xfree(span->backtrace);
  951. yasm_xfree(span);
  952. }
  953. static void
  954. optimize_cleanup(optimize_data *optd)
  955. {
  956. yasm_span *s1, *s2;
  957. yasm_offset_setter *os1, *os2;
  958. IT_destroy(optd->itree);
  959. s1 = TAILQ_FIRST(&optd->spans);
  960. while (s1) {
  961. s2 = TAILQ_NEXT(s1, link);
  962. span_destroy(s1);
  963. s1 = s2;
  964. }
  965. os1 = STAILQ_FIRST(&optd->offset_setters);
  966. while (os1) {
  967. os2 = STAILQ_NEXT(os1, link);
  968. yasm_xfree(os1);
  969. os1 = os2;
  970. }
  971. }
  972. static void
  973. optimize_itree_add(IntervalTree *itree, yasm_span *span, yasm_span_term *term)
  974. {
  975. long precbc_index, precbc2_index;
  976. unsigned long low, high;
  977. /* Update term length */
  978. if (term->precbc)
  979. precbc_index = term->precbc->bc_index;
  980. else
  981. precbc_index = span->bc->bc_index-1;
  982. if (term->precbc2)
  983. precbc2_index = term->precbc2->bc_index;
  984. else
  985. precbc2_index = span->bc->bc_index-1;
  986. if (precbc_index < precbc2_index) {
  987. low = precbc_index+1;
  988. high = precbc2_index;
  989. } else if (precbc_index > precbc2_index) {
  990. low = precbc2_index+1;
  991. high = precbc_index;
  992. } else
  993. return; /* difference is same bc - always 0! */
  994. IT_insert(itree, (long)low, (long)high, term);
  995. }
  996. static void
  997. check_cycle(IntervalTreeNode *node, void *d)
  998. {
  999. optimize_data *optd = d;
  1000. yasm_span_term *term = node->data;
  1001. yasm_span *depspan = term->span;
  1002. int i;
  1003. int depspan_bt_alloc;
  1004. /* Only check for cycles in id=0 spans */
  1005. if (depspan->id > 0)
  1006. return;
  1007. /* Check for a circular reference by looking to see if this dependent
  1008. * span is in our backtrace.
  1009. */
  1010. if (optd->span->backtrace) {
  1011. for (i=0; i<optd->span->backtrace_size; i++) {
  1012. if (optd->span->backtrace[i] == depspan)
  1013. yasm_error_set(YASM_ERROR_VALUE,
  1014. N_("circular reference detected"));
  1015. }
  1016. }
  1017. /* Add our complete backtrace and ourselves to backtrace of dependent
  1018. * span.
  1019. */
  1020. if (!depspan->backtrace) {
  1021. depspan->backtrace = yasm_xmalloc((optd->span->backtrace_size+1)*
  1022. sizeof(yasm_span *));
  1023. if (optd->span->backtrace_size > 0)
  1024. memcpy(depspan->backtrace, optd->span->backtrace,
  1025. optd->span->backtrace_size*sizeof(yasm_span *));
  1026. depspan->backtrace[optd->span->backtrace_size] = optd->span;
  1027. depspan->backtrace_size = optd->span->backtrace_size+1;
  1028. return;
  1029. }
  1030. /* Add our complete backtrace, checking for duplicates */
  1031. depspan_bt_alloc = depspan->backtrace_size;
  1032. for (i=0; i<optd->span->backtrace_size; i++) {
  1033. int present = 0;
  1034. int j;
  1035. for (j=0; j<depspan->backtrace_size; j++) {
  1036. if (optd->span->backtrace[i] == optd->span->backtrace[j]) {
  1037. present = 1;
  1038. break;
  1039. }
  1040. }
  1041. if (present)
  1042. continue;
  1043. /* Not already in array; add it. */
  1044. if (depspan->backtrace_size >= depspan_bt_alloc)
  1045. {
  1046. depspan_bt_alloc *= 2;
  1047. depspan->backtrace =
  1048. yasm_xrealloc(depspan->backtrace,
  1049. depspan_bt_alloc*sizeof(yasm_span *));
  1050. }
  1051. depspan->backtrace[depspan->backtrace_size] = optd->span->backtrace[i];
  1052. depspan->backtrace_size++;
  1053. }
  1054. /* Add ourselves. */
  1055. if (depspan->backtrace_size >= depspan_bt_alloc)
  1056. {
  1057. depspan_bt_alloc++;
  1058. depspan->backtrace =
  1059. yasm_xrealloc(depspan->backtrace,
  1060. depspan_bt_alloc*sizeof(yasm_span *));
  1061. }
  1062. depspan->backtrace[depspan->backtrace_size] = optd->span;
  1063. depspan->backtrace_size++;
  1064. }
  1065. static void
  1066. optimize_term_expand(IntervalTreeNode *node, void *d)
  1067. {
  1068. optimize_data *optd = d;
  1069. yasm_span_term *term = node->data;
  1070. yasm_span *span = term->span;
  1071. long len_diff = optd->len_diff;
  1072. long precbc_index, precbc2_index;
  1073. /* Don't expand inactive spans */
  1074. if (!span->active)
  1075. return;
  1076. /* Update term length */
  1077. if (term->precbc)
  1078. precbc_index = term->precbc->bc_index;
  1079. else
  1080. precbc_index = span->bc->bc_index-1;
  1081. if (term->precbc2)
  1082. precbc2_index = term->precbc2->bc_index;
  1083. else
  1084. precbc2_index = span->bc->bc_index-1;
  1085. if (precbc_index < precbc2_index)
  1086. term->new_val += len_diff;
  1087. else
  1088. term->new_val -= len_diff;
  1089. /* If already on Q, don't re-add */
  1090. if (span->active == 2)
  1091. return;
  1092. /* Update term and check against thresholds */
  1093. if (!recalc_normal_span(span))
  1094. return; /* didn't exceed thresholds, we're done */
  1095. /* Exceeded thresholds, need to add to Q for expansion */
  1096. if (span->id <= 0)
  1097. STAILQ_INSERT_TAIL(&optd->QA, span, linkq);
  1098. else
  1099. STAILQ_INSERT_TAIL(&optd->QB, span, linkq);
  1100. span->active = 2; /* Mark as being in Q */
  1101. }
  1102. void
  1103. yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns)
  1104. {
  1105. yasm_section *sect;
  1106. unsigned long bc_index = 0;
  1107. int saw_error = 0;
  1108. optimize_data optd;
  1109. yasm_span *span, *span_temp;
  1110. yasm_offset_setter *os;
  1111. int retval;
  1112. unsigned int i;
  1113. TAILQ_INIT(&optd.spans);
  1114. STAILQ_INIT(&optd.offset_setters);
  1115. optd.itree = IT_create();
  1116. /* Create an placeholder offset setter for spans to point to; this will
  1117. * get updated if/when we actually run into one.
  1118. */
  1119. os = yasm_xmalloc(sizeof(yasm_offset_setter));
  1120. os->bc = NULL;
  1121. os->cur_val = 0;
  1122. os->new_val = 0;
  1123. os->thres = 0;
  1124. STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
  1125. optd.os = os;
  1126. /* Step 1a */
  1127. STAILQ_FOREACH(sect, &object->sections, link) {
  1128. unsigned long offset = 0;
  1129. yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
  1130. bc->bc_index = bc_index++;
  1131. /* Skip our locally created empty bytecode first. */
  1132. bc = STAILQ_NEXT(bc, link);
  1133. /* Iterate through the remainder, if any. */
  1134. while (bc) {
  1135. bc->bc_index = bc_index++;
  1136. bc->offset = offset;
  1137. retval = yasm_bc_calc_len(bc, optimize_add_span, &optd);
  1138. yasm_errwarn_propagate(errwarns, bc->line);
  1139. if (retval)
  1140. saw_error = 1;
  1141. else {
  1142. if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
  1143. /* Remember it as offset setter */
  1144. os->bc = bc;
  1145. os->thres = yasm_bc_next_offset(bc);
  1146. /* Create new placeholder */
  1147. os = yasm_xmalloc(sizeof(yasm_offset_setter));
  1148. os->bc = NULL;
  1149. os->cur_val = 0;
  1150. os->new_val = 0;
  1151. os->thres = 0;
  1152. STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
  1153. optd.os = os;
  1154. if (bc->multiple) {
  1155. yasm_error_set(YASM_ERROR_VALUE,
  1156. N_("cannot combine multiples and setting assembly position"));
  1157. yasm_errwarn_propagate(errwarns, bc->line);
  1158. saw_error = 1;
  1159. }
  1160. }
  1161. offset += bc->len*bc->mult_int;
  1162. }
  1163. bc = STAILQ_NEXT(bc, link);
  1164. }
  1165. }
  1166. if (saw_error) {
  1167. optimize_cleanup(&optd);
  1168. return;
  1169. }
  1170. /* Step 1b */
  1171. TAILQ_FOREACH_SAFE(span, &optd.spans, link, span_temp) {
  1172. span_create_terms(span);
  1173. if (yasm_error_occurred()) {
  1174. yasm_errwarn_propagate(errwarns, span->bc->line);
  1175. saw_error = 1;
  1176. } else if (recalc_normal_span(span)) {
  1177. retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
  1178. span->new_val, &span->neg_thres,
  1179. &span->pos_thres);
  1180. yasm_errwarn_propagate(errwarns, span->bc->line);
  1181. if (retval < 0)
  1182. saw_error = 1;
  1183. else if (retval > 0) {
  1184. if (!span->active) {
  1185. yasm_error_set(YASM_ERROR_VALUE,
  1186. N_("secondary expansion of an external/complex value"));
  1187. yasm_errwarn_propagate(errwarns, span->bc->line);
  1188. saw_error = 1;
  1189. }
  1190. } else {
  1191. TAILQ_REMOVE(&optd.spans, span, link);
  1192. span_destroy(span);
  1193. continue;
  1194. }
  1195. }
  1196. span->cur_val = span->new_val;
  1197. }
  1198. if (saw_error) {
  1199. optimize_cleanup(&optd);
  1200. return;
  1201. }
  1202. /* Step 1c */
  1203. if (update_all_bc_offsets(object, errwarns)) {
  1204. optimize_cleanup(&optd);
  1205. return;
  1206. }
  1207. /* Step 1d */
  1208. STAILQ_INIT(&optd.QB);
  1209. TAILQ_FOREACH(span, &optd.spans, link) {
  1210. yasm_intnum *intn;
  1211. /* Update span terms based on new bc offsets */
  1212. for (i=0; i<span->num_terms; i++) {
  1213. intn = yasm_calc_bc_dist(span->terms[i].precbc,
  1214. span->terms[i].precbc2);
  1215. if (!intn)
  1216. yasm_internal_error(N_("could not calculate bc distance"));
  1217. span->terms[i].cur_val = span->terms[i].new_val;
  1218. span->terms[i].new_val = yasm_intnum_get_int(intn);
  1219. yasm_intnum_destroy(intn);
  1220. }
  1221. if (span->rel_term) {
  1222. span->rel_term->cur_val = span->rel_term->new_val;
  1223. if (span->rel_term->precbc2)
  1224. span->rel_term->new_val =
  1225. yasm_bc_next_offset(span->rel_term->precbc2) -
  1226. span->bc->offset;
  1227. else
  1228. span->rel_term->new_val = span->bc->offset -
  1229. yasm_bc_next_offset(span->rel_term->precbc);
  1230. }
  1231. if (recalc_normal_span(span)) {
  1232. /* Exceeded threshold, add span to QB */
  1233. STAILQ_INSERT_TAIL(&optd.QB, span, linkq);
  1234. span->active = 2;
  1235. }
  1236. }
  1237. /* Do we need step 2? If not, go ahead and exit. */
  1238. if (STAILQ_EMPTY(&optd.QB)) {
  1239. optimize_cleanup(&optd);
  1240. return;
  1241. }
  1242. /* Update offset-setters values */
  1243. STAILQ_FOREACH(os, &optd.offset_setters, link) {
  1244. if (!os->bc)
  1245. continue;
  1246. os->thres = yasm_bc_next_offset(os->bc);
  1247. os->new_val = os->bc->offset;
  1248. os->cur_val = os->new_val;
  1249. }
  1250. /* Build up interval tree */
  1251. TAILQ_FOREACH(span, &optd.spans, link) {
  1252. for (i=0; i<span->num_terms; i++)
  1253. optimize_itree_add(optd.itree, span, &span->terms[i]);
  1254. if (span->rel_term)
  1255. optimize_itree_add(optd.itree, span, span->rel_term);
  1256. }
  1257. /* Look for cycles in times expansion (span.id==0) */
  1258. TAILQ_FOREACH(span, &optd.spans, link) {
  1259. if (span->id > 0)
  1260. continue;
  1261. optd.span = span;
  1262. IT_enumerate(optd.itree, (long)span->bc->bc_index,
  1263. (long)span->bc->bc_index, &optd, check_cycle);
  1264. if (yasm_error_occurred()) {
  1265. yasm_errwarn_propagate(errwarns, span->bc->line);
  1266. saw_error = 1;
  1267. }
  1268. }
  1269. if (saw_error) {
  1270. optimize_cleanup(&optd);
  1271. return;
  1272. }
  1273. /* Step 2 */
  1274. STAILQ_INIT(&optd.QA);
  1275. while (!STAILQ_EMPTY(&optd.QA) || !(STAILQ_EMPTY(&optd.QB))) {
  1276. unsigned long orig_len;
  1277. long offset_diff;
  1278. /* QA is for TIMES, update those first, then update non-TIMES.
  1279. * This is so that TIMES can absorb increases before we look at
  1280. * expanding non-TIMES BCs.
  1281. */
  1282. if (!STAILQ_EMPTY(&optd.QA)) {
  1283. span = STAILQ_FIRST(&optd.QA);
  1284. STAILQ_REMOVE_HEAD(&optd.QA, linkq);
  1285. } else {
  1286. span = STAILQ_FIRST(&optd.QB);
  1287. STAILQ_REMOVE_HEAD(&optd.QB, linkq);
  1288. }
  1289. if (!span->active)
  1290. continue;
  1291. span->active = 1; /* no longer in Q */
  1292. /* Make sure we ended up ultimately exceeding thresholds; due to
  1293. * offset BCs we may have been placed on Q and then reduced in size
  1294. * again.
  1295. */
  1296. if (!recalc_normal_span(span))
  1297. continue;
  1298. orig_len = span->bc->len * span->bc->mult_int;
  1299. retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
  1300. span->new_val, &span->neg_thres,
  1301. &span->pos_thres);
  1302. yasm_errwarn_propagate(errwarns, span->bc->line);
  1303. if (retval < 0) {
  1304. /* error */
  1305. saw_error = 1;
  1306. continue;
  1307. } else if (retval > 0) {
  1308. /* another threshold, keep active */
  1309. for (i=0; i<span->num_terms; i++)
  1310. span->terms[i].cur_val = span->terms[i].new_val;
  1311. if (span->rel_term)
  1312. span->rel_term->cur_val = span->rel_term->new_val;
  1313. span->cur_val = span->new_val;
  1314. } else
  1315. span->active = 0; /* we're done with this span */
  1316. optd.len_diff = span->bc->len * span->bc->mult_int - orig_len;
  1317. if (optd.len_diff == 0)
  1318. continue; /* didn't increase in size */
  1319. /* Iterate over all spans dependent across the bc just expanded */
  1320. IT_enumerate(optd.itree, (long)span->bc->bc_index,
  1321. (long)span->bc->bc_index, &optd, optimize_term_expand);
  1322. /* Iterate over offset-setters that follow the bc just expanded.
  1323. * Stop iteration if:
  1324. * - no more offset-setters in this section
  1325. * - offset-setter didn't move its following offset
  1326. */
  1327. os = span->os;
  1328. offset_diff = optd.len_diff;
  1329. while (os->bc && os->bc->section == span->bc->section
  1330. && offset_diff != 0) {
  1331. unsigned long old_next_offset = os->cur_val + os->bc->len;
  1332. long neg_thres_temp;
  1333. if (offset_diff < 0 && (unsigned long)(-offset_diff) > os->new_val)
  1334. yasm_internal_error(N_("org/align went to negative offset"));
  1335. os->new_val += offset_diff;
  1336. orig_len = os->bc->len;
  1337. retval = yasm_bc_expand(os->bc, 1, (long)os->cur_val,
  1338. (long)os->new_val, &neg_thres_temp,
  1339. (long *)&os->thres);
  1340. yasm_errwarn_propagate(errwarns, os->bc->line);
  1341. offset_diff = os->new_val + os->bc->len - old_next_offset;
  1342. optd.len_diff = os->bc->len - orig_len;
  1343. if (optd.len_diff != 0)
  1344. IT_enumerate(optd.itree, (long)os->bc->bc_index,
  1345. (long)os->bc->bc_index, &optd, optimize_term_expand);
  1346. os->cur_val = os->new_val;
  1347. os = STAILQ_NEXT(os, link);
  1348. }
  1349. }
  1350. if (saw_error) {
  1351. optimize_cleanup(&optd);
  1352. return;
  1353. }
  1354. /* Step 3 */
  1355. update_all_bc_offsets(object, errwarns);
  1356. optimize_cleanup(&optd);
  1357. }