mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
Implement first phase of align and org.
svn path=/branches/new-optimizer/; revision=1567
This commit is contained in:
parent
53d9be8757
commit
114cee8b06
10 changed files with 218 additions and 162 deletions
|
|
@ -71,7 +71,7 @@ static const yasm_bytecode_callback bc_align_callback = {
|
|||
bc_align_calc_len,
|
||||
bc_align_expand,
|
||||
bc_align_tobytes,
|
||||
0
|
||||
YASM_BC_SPECIAL_OFFSET
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -121,31 +121,13 @@ static int
|
|||
bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
|
||||
void *add_span_data)
|
||||
{
|
||||
yasm_internal_error(N_("align not yet implemented"));
|
||||
#if 0
|
||||
bytecode_align *align = (bytecode_align *)bc->contents;
|
||||
unsigned long end;
|
||||
unsigned long boundary =
|
||||
yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL));
|
||||
long neg_thres = 0;
|
||||
long pos_thres = 0;
|
||||
|
||||
if (boundary == 0) {
|
||||
bc->len = 0;
|
||||
return YASM_BC_RESOLVE_MIN_LEN;
|
||||
}
|
||||
if (bc_align_expand(bc, 0, 0, (long)bc->offset, &neg_thres,
|
||||
&pos_thres) < 0)
|
||||
return -1;
|
||||
|
||||
end = bc->offset;
|
||||
if (bc->offset & (boundary-1))
|
||||
end = (bc->offset & ~(boundary-1)) + boundary;
|
||||
|
||||
bc->len = end - bc->offset;
|
||||
|
||||
if (align->maxskip) {
|
||||
unsigned long maxskip =
|
||||
yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, NULL));
|
||||
if ((end - bc->offset) > maxskip)
|
||||
bc->len = 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -153,8 +135,31 @@ static int
|
|||
bc_align_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
|
||||
/*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
|
||||
{
|
||||
yasm_internal_error(N_("align not yet implemented"));
|
||||
return 0;
|
||||
bytecode_align *align = (bytecode_align *)bc->contents;
|
||||
unsigned long end;
|
||||
unsigned long boundary =
|
||||
yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));
|
||||
|
||||
if (boundary == 0) {
|
||||
bc->len = 0;
|
||||
*pos_thres = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
end = new_val;
|
||||
if (new_val & (boundary-1))
|
||||
end = (new_val & ~(boundary-1)) + boundary;
|
||||
|
||||
*pos_thres = end;
|
||||
bc->len = end - new_val;
|
||||
|
||||
if (align->maxskip) {
|
||||
unsigned long maxskip =
|
||||
yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
|
||||
if ((end - new_val) > maxskip)
|
||||
bc->len = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -38,7 +38,11 @@ typedef struct yasm_bytecode_callback {
|
|||
int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, void *d,
|
||||
yasm_output_value_func output_value,
|
||||
/*@null@*/ yasm_output_reloc_func output_reloc);
|
||||
int reserve; /* Reserve space instead of outputting data */
|
||||
enum {
|
||||
YASM_BC_SPECIAL_NONE = 0,
|
||||
YASM_BC_SPECIAL_RESERVE,/* Reserves space instead of outputting data */
|
||||
YASM_BC_SPECIAL_OFFSET /* Adjusts offset instead of calculating len */
|
||||
} special;
|
||||
} yasm_bytecode_callback;
|
||||
|
||||
struct yasm_bytecode {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ static const yasm_bytecode_callback bc_org_callback = {
|
|||
bc_org_calc_len,
|
||||
bc_org_expand,
|
||||
bc_org_tobytes,
|
||||
0
|
||||
YASM_BC_SPECIAL_OFFSET
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -91,20 +91,13 @@ static int
|
|||
bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
|
||||
void *add_span_data)
|
||||
{
|
||||
yasm_internal_error(N_("org not yet implemented"));
|
||||
#if 0
|
||||
bytecode_org *org = (bytecode_org *)bc->contents;
|
||||
long neg_thres = 0;
|
||||
long pos_thres = org->start;
|
||||
|
||||
/* Check for overrun */
|
||||
if (bc->offset > org->start) {
|
||||
yasm_error_set(YASM_ERROR_GENERAL,
|
||||
N_("ORG overlap with already existing data"));
|
||||
return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
|
||||
}
|
||||
if (bc_org_expand(bc, 0, 0, (long)bc->offset, &neg_thres, &pos_thres) < 0)
|
||||
return -1;
|
||||
|
||||
/* Generate space to start offset */
|
||||
bc->len = org->start - bc->offset;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -112,8 +105,18 @@ static int
|
|||
bc_org_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
|
||||
/*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
|
||||
{
|
||||
yasm_internal_error(N_("org not yet implemented"));
|
||||
return 0;
|
||||
bytecode_org *org = (bytecode_org *)bc->contents;
|
||||
|
||||
/* Check for overrun */
|
||||
if ((unsigned long)new_val > org->start) {
|
||||
yasm_error_set(YASM_ERROR_GENERAL,
|
||||
N_("ORG overlap with already existing data"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate space to start offset */
|
||||
bc->len = org->start - new_val;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static const yasm_bytecode_callback bc_reserve_callback = {
|
|||
bc_reserve_calc_len,
|
||||
yasm_bc_expand_common,
|
||||
bc_reserve_tobytes,
|
||||
1
|
||||
YASM_BC_SPECIAL_RESERVE
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -83,20 +83,13 @@ yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents,
|
|||
yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode));
|
||||
|
||||
bc->callback = callback;
|
||||
|
||||
bc->section = NULL;
|
||||
|
||||
bc->multiple = (yasm_expr *)NULL;
|
||||
bc->len = 0;
|
||||
|
||||
bc->line = line;
|
||||
|
||||
bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
|
||||
|
||||
bc->opt_flags = 0;
|
||||
|
||||
bc->symrecs = NULL;
|
||||
|
||||
bc->contents = contents;
|
||||
|
||||
return bc;
|
||||
|
|
@ -206,29 +199,31 @@ yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
|
|||
bc->len = 0;
|
||||
|
||||
if (!bc->callback)
|
||||
yasm_internal_error(N_("got empty bytecode in bc_resolve"));
|
||||
yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len"));
|
||||
else
|
||||
retval = bc->callback->calc_len(bc, add_span, add_span_data);
|
||||
#if 0
|
||||
|
||||
/* Check for multiples */
|
||||
if (bc->multiple) {
|
||||
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
|
||||
|
||||
num = yasm_expr_get_intnum(&bc->multiple, NULL);
|
||||
if (!num) {
|
||||
num = yasm_expr_get_intnum(&bc->multiple, 0);
|
||||
if (num)
|
||||
bc->len *= yasm_intnum_get_uint(num);
|
||||
else {
|
||||
if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
|
||||
yasm_error_set(YASM_ERROR_VALUE,
|
||||
N_("expression must not contain floating point value"));
|
||||
retval = -1;
|
||||
} else {
|
||||
/* FIXME: Non-constant currently not allowed. */
|
||||
yasm__error(bc->line,
|
||||
N_("attempt to use non-constant multiple"));
|
||||
yasm_error_set(YASM_ERROR_VALUE,
|
||||
N_("attempt to use non-constant multiple"));
|
||||
retval = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we got an error somewhere along the line, clear out any calc len */
|
||||
if (retval < 0)
|
||||
bc->len = 0;
|
||||
|
|
@ -241,7 +236,7 @@ yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
|
|||
/*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
|
||||
{
|
||||
if (!bc->callback) {
|
||||
yasm_internal_error(N_("got empty bytecode in bc_set_long"));
|
||||
yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
|
||||
/*@unreached@*/
|
||||
return 0;
|
||||
} else
|
||||
|
|
@ -267,7 +262,7 @@ yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
|
|||
}
|
||||
|
||||
/* special case for reserve bytecodes */
|
||||
if (bc->callback->reserve) {
|
||||
if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
|
||||
*bufsize = bc->len;
|
||||
*gap = 1;
|
||||
return NULL; /* we didn't allocate a buffer */
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
|
|||
* \param pos_thres positive threshold for long/short decision
|
||||
*/
|
||||
typedef void (*yasm_bc_add_span_func)
|
||||
(void *add_span_data, yasm_bytecode *bc, int id, yasm_value *value,
|
||||
(void *add_span_data, yasm_bytecode *bc, int id, const yasm_value *value,
|
||||
long neg_thres, long pos_thres);
|
||||
|
||||
/** Resolve EQUs in a bytecode and calculate its minimum size.
|
||||
|
|
|
|||
|
|
@ -648,20 +648,19 @@ yasm_section_print(const yasm_section *sect, FILE *f, int indent_level,
|
|||
* Some portions are critical values that must not depend on any bytecode
|
||||
* offset (either relative or absolute).
|
||||
*
|
||||
* ALIGN: 0 length (always). Bump offset to alignment. Span from 0 to
|
||||
* align bytecode, update on any change. If span length
|
||||
* increases past alignment, increase offset by alignment and update
|
||||
* dependent spans. Alignment is critical value.
|
||||
* ORG: Same as align, but if span's length exceeds org value, error.
|
||||
* ORG value is critical value.
|
||||
* ALIGN/ORG/other offset-based bytecodes: Length set to bump offset to
|
||||
* alignment. Span from 0 to bytecode, update on any change. Can
|
||||
* update to new offset for things like align, which gets propagated
|
||||
* to update dependent spans. Alignment/ORG value is critical value.
|
||||
* Cannot be combined with TIMES.
|
||||
*
|
||||
* How times is handled:
|
||||
*
|
||||
* TIMES: Handled separately from bytecode "raw" size. If not span-dependent,
|
||||
* trivial (just multiplied in at any bytecode size increase). Span
|
||||
* dependent times update on any change (span ID 0). If the resultant
|
||||
* next bytecode offset would be less than the old next bytecode offset,
|
||||
* error. Otherwise increase offset and update dependent spans.
|
||||
* trivial (just multiplied in at any bytecode size increase). Span
|
||||
* dependent times update on any change (span ID 0). If the resultant
|
||||
* next bytecode offset would be less than the old next bytecode offset,
|
||||
* error. Otherwise increase offset and update dependent spans.
|
||||
*
|
||||
* To reduce interval tree size, a first expansion pass is performed
|
||||
* before the spans are added to the tree.
|
||||
|
|
@ -673,9 +672,8 @@ yasm_section_print(const yasm_section *sect, FILE *f, int indent_level,
|
|||
* of all bytecodes assuming minimum length, building a list of all
|
||||
* dependent spans as we go.
|
||||
* "minimum" here means absolute minimum:
|
||||
* - align 0 length, but bumps offset
|
||||
* - align/org (offset-based) bumps offset as normal
|
||||
* - times values (with span-dependent values) assumed to be 0
|
||||
* - org 0 length, but bumps offset
|
||||
* b. Iterate over spans. Set span length based on bytecode offsets
|
||||
* determined in 1a. If span is "certainly" long because the span
|
||||
* is an absolute reference to another section (or external) or the
|
||||
|
|
@ -707,13 +705,12 @@ typedef struct yasm_span {
|
|||
|
||||
/*@dependent@*/ yasm_bytecode *bc;
|
||||
|
||||
yasm_value *depval;
|
||||
yasm_value depval;
|
||||
|
||||
/* Special handling: see descriptions above */
|
||||
enum {
|
||||
NOT_SPECIAL = 0,
|
||||
SPECIAL_ALIGN,
|
||||
SPECIAL_ORG,
|
||||
SPECIAL_BC_OFFSET,
|
||||
SPECIAL_TIMES
|
||||
} special;
|
||||
|
||||
|
|
@ -734,13 +731,13 @@ typedef struct optimize_data {
|
|||
|
||||
static void
|
||||
optimize_add_span(void *add_span_data, yasm_bytecode *bc, int id,
|
||||
yasm_value *value, long neg_thres, long pos_thres)
|
||||
const yasm_value *value, long neg_thres, long pos_thres)
|
||||
{
|
||||
optimize_data *optd = (optimize_data *)add_span_data;
|
||||
yasm_span *span = yasm_xmalloc(sizeof(yasm_span));
|
||||
|
||||
span->bc = bc;
|
||||
span->depval = value;
|
||||
yasm_value_init_copy(&span->depval, value);
|
||||
span->special = NOT_SPECIAL;
|
||||
span->cur_val = 0;
|
||||
span->new_val = 0;
|
||||
|
|
@ -752,29 +749,42 @@ optimize_add_span(void *add_span_data, yasm_bytecode *bc, int id,
|
|||
STAILQ_INSERT_TAIL(&optd->spans, span, link);
|
||||
}
|
||||
|
||||
static void
|
||||
update_all_bc_offsets(yasm_object *object)
|
||||
static int
|
||||
update_all_bc_offsets(yasm_object *object, yasm_errwarns *errwarns)
|
||||
{
|
||||
yasm_section *sect;
|
||||
int saw_error = 0;
|
||||
|
||||
STAILQ_FOREACH(sect, &object->sections, link) {
|
||||
unsigned long offset = 0;
|
||||
|
||||
yasm_bytecode *cur = STAILQ_FIRST(§->bcs);
|
||||
yasm_bytecode *prev;
|
||||
yasm_bytecode *bc = STAILQ_FIRST(§->bcs);
|
||||
yasm_bytecode *prevbc;
|
||||
|
||||
/* Skip our locally created empty bytecode first. */
|
||||
prev = cur;
|
||||
cur = STAILQ_NEXT(cur, link);
|
||||
prevbc = bc;
|
||||
bc = STAILQ_NEXT(bc, link);
|
||||
|
||||
/* Iterate through the remainder, if any. */
|
||||
while (cur) {
|
||||
cur->offset = offset;
|
||||
offset += cur->len;
|
||||
prev = cur;
|
||||
cur = STAILQ_NEXT(cur, link);
|
||||
while (bc) {
|
||||
if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
|
||||
/* Recalculate/adjust len of offset-based bytecodes here */
|
||||
long neg_thres = 0;
|
||||
long pos_thres = bc->offset+bc->len;
|
||||
int retval = yasm_bc_expand(bc, 0, 0,
|
||||
(long)(prevbc->offset+prevbc->len),
|
||||
&neg_thres, &pos_thres);
|
||||
yasm_errwarn_propagate(errwarns, bc->line);
|
||||
if (retval < 0)
|
||||
saw_error = 1;
|
||||
}
|
||||
bc->offset = offset;
|
||||
offset += bc->len;
|
||||
prevbc = bc;
|
||||
bc = STAILQ_NEXT(bc, link);
|
||||
}
|
||||
}
|
||||
return saw_error;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -797,31 +807,55 @@ yasm_object_optimize(yasm_object *object, yasm_arch *arch,
|
|||
STAILQ_FOREACH(sect, &object->sections, link) {
|
||||
unsigned long offset = 0;
|
||||
|
||||
yasm_bytecode *cur = STAILQ_FIRST(§->bcs);
|
||||
yasm_bytecode *prev;
|
||||
yasm_bytecode *bc = STAILQ_FIRST(§->bcs);
|
||||
yasm_bytecode *prevbc;
|
||||
|
||||
cur->bc_index = bc_index++;
|
||||
bc->bc_index = bc_index++;
|
||||
|
||||
/* Skip our locally created empty bytecode first. */
|
||||
prev = cur;
|
||||
cur = STAILQ_NEXT(cur, link);
|
||||
prevbc = bc;
|
||||
bc = STAILQ_NEXT(bc, link);
|
||||
|
||||
/* Iterate through the remainder, if any. */
|
||||
while (cur) {
|
||||
cur->bc_index = bc_index++;
|
||||
while (bc) {
|
||||
bc->bc_index = bc_index++;
|
||||
bc->offset = offset;
|
||||
|
||||
if (yasm_bc_calc_len(cur, optimize_add_span, &optd))
|
||||
retval = yasm_bc_calc_len(bc, optimize_add_span, &optd);
|
||||
yasm_errwarn_propagate(errwarns, bc->line);
|
||||
if (retval)
|
||||
saw_error = 1;
|
||||
yasm_errwarn_propagate(errwarns, cur->line);
|
||||
else {
|
||||
if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
|
||||
span = yasm_xmalloc(sizeof(yasm_span));
|
||||
|
||||
/* TODO: times */
|
||||
if (cur->multiple)
|
||||
yasm_internal_error("multiple not yet supported");
|
||||
span->bc = bc;
|
||||
yasm_value_initialize(&span->depval, NULL, 0);
|
||||
span->special = SPECIAL_BC_OFFSET;
|
||||
span->cur_val = (long)(prevbc->offset+prevbc->len);
|
||||
span->new_val = 0;
|
||||
span->neg_thres = 0;
|
||||
span->pos_thres = (long)(bc->offset+bc->len);
|
||||
span->id = 0;
|
||||
span->active = 1;
|
||||
|
||||
cur->offset = offset;
|
||||
offset += cur->len;
|
||||
prev = cur;
|
||||
cur = STAILQ_NEXT(cur, link);
|
||||
STAILQ_INSERT_TAIL(&optd.spans, span, link);
|
||||
if (bc->multiple) {
|
||||
yasm_error_set(YASM_ERROR_VALUE,
|
||||
N_("cannot combine multiples and setting assembly position"));
|
||||
yasm_errwarn_propagate(errwarns, span->bc->line);
|
||||
saw_error = 1;
|
||||
}
|
||||
}
|
||||
/* TODO: times */
|
||||
if (bc->len != 0 && bc->multiple) {
|
||||
yasm_internal_error("multiple not yet supported");
|
||||
}
|
||||
offset += bc->len;
|
||||
}
|
||||
|
||||
prevbc = bc;
|
||||
bc = STAILQ_NEXT(bc, link);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -832,47 +866,61 @@ yasm_object_optimize(yasm_object *object, yasm_arch *arch,
|
|||
STAILQ_FOREACH(span, &optd.spans, link) {
|
||||
if (!span->active)
|
||||
continue;
|
||||
yasm_value_init_copy(&val, span->depval);
|
||||
num = yasm_value_get_intnum(&val, span->bc, 1);
|
||||
if (num) {
|
||||
span->new_val = yasm_intnum_get_int(num);
|
||||
yasm_intnum_destroy(num);
|
||||
} else {
|
||||
/* external or too complex; force to longer form */
|
||||
span->new_val = LONG_MAX;
|
||||
span->active = 0;
|
||||
}
|
||||
yasm_value_delete(&val);
|
||||
|
||||
if ((span->id == 0 && span->new_val != span->cur_val) ||
|
||||
(span->new_val < span->neg_thres
|
||||
|| span->new_val > span->pos_thres)) {
|
||||
retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
|
||||
span->new_val, &neg_thres, &pos_thres);
|
||||
yasm_errwarn_propagate(errwarns, span->bc->line);
|
||||
if (retval < 0)
|
||||
saw_error = 1;
|
||||
else if (retval > 0) {
|
||||
if (!span->active) {
|
||||
yasm_error_set(YASM_ERROR_VALUE,
|
||||
N_("secondary expansion of an external/complex value"));
|
||||
yasm_errwarn_propagate(errwarns, span->bc->line);
|
||||
saw_error = 1;
|
||||
switch (span->special) {
|
||||
case NOT_SPECIAL:
|
||||
yasm_value_init_copy(&val, &span->depval);
|
||||
num = yasm_value_get_intnum(&val, span->bc, 1);
|
||||
if (num) {
|
||||
span->new_val = yasm_intnum_get_int(num);
|
||||
yasm_intnum_destroy(num);
|
||||
} else {
|
||||
span->neg_thres = neg_thres;
|
||||
span->pos_thres = pos_thres;
|
||||
/* external or too complex; force to longest form */
|
||||
span->new_val = LONG_MAX;
|
||||
span->active = 0;
|
||||
}
|
||||
} else
|
||||
span->active = 0;
|
||||
yasm_value_delete(&val);
|
||||
|
||||
if ((span->id == 0 && span->new_val != span->cur_val) ||
|
||||
(span->new_val < span->neg_thres
|
||||
|| span->new_val > span->pos_thres)) {
|
||||
retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
|
||||
span->new_val, &neg_thres,
|
||||
&pos_thres);
|
||||
yasm_errwarn_propagate(errwarns, span->bc->line);
|
||||
if (retval < 0)
|
||||
saw_error = 1;
|
||||
else if (retval > 0) {
|
||||
if (!span->active) {
|
||||
yasm_error_set(YASM_ERROR_VALUE,
|
||||
N_("secondary expansion of an external/complex value"));
|
||||
yasm_errwarn_propagate(errwarns, span->bc->line);
|
||||
saw_error = 1;
|
||||
} else {
|
||||
span->neg_thres = neg_thres;
|
||||
span->pos_thres = pos_thres;
|
||||
}
|
||||
} else
|
||||
span->active = 0;
|
||||
}
|
||||
span->cur_val = span->new_val;
|
||||
if (span->active) {
|
||||
/* Add to interval tree */
|
||||
}
|
||||
break;
|
||||
case SPECIAL_BC_OFFSET:
|
||||
/* Add to interval tree; nothing else to do here */
|
||||
break;
|
||||
case SPECIAL_TIMES:
|
||||
break;
|
||||
}
|
||||
span->cur_val = span->new_val;
|
||||
}
|
||||
|
||||
if (saw_error)
|
||||
return;
|
||||
|
||||
/* Step 1c */
|
||||
update_all_bc_offsets(object);
|
||||
if (update_all_bc_offsets(object, errwarns))
|
||||
return;
|
||||
|
||||
/* Step 1d */
|
||||
STAILQ_FOREACH(span, &optd.spans, link) {
|
||||
|
|
@ -883,5 +931,5 @@ yasm_object_optimize(yasm_object *object, yasm_arch *arch,
|
|||
/* Step 2 */
|
||||
|
||||
/* Step 3 */
|
||||
update_all_bc_offsets(object);
|
||||
update_all_bc_offsets(object, errwarns);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -494,31 +494,33 @@ yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist)
|
|||
}
|
||||
|
||||
if (value->rel) {
|
||||
/* If relative portion is not in bc section, return NULL.
|
||||
* Otherwise get the relative portion's offset.
|
||||
*/
|
||||
/* Get the relative portion's offset. */
|
||||
/*@dependent@*/ yasm_bytecode *rel_prevbc;
|
||||
unsigned long dist;
|
||||
|
||||
if (!bc)
|
||||
return NULL; /* Can't calculate relative value */
|
||||
if (!calc_bc_dist)
|
||||
return NULL; /* Don't calculate BC distance */
|
||||
|
||||
sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
|
||||
if (value->wrt || value->seg_of || value->section_rel || !sym_local)
|
||||
return NULL; /* we can't handle SEG, WRT, or external symbols */
|
||||
if (rel_prevbc->section != bc->section)
|
||||
return NULL; /* not in this section */
|
||||
if (!value->curpos_rel)
|
||||
return NULL; /* not PC-relative */
|
||||
|
||||
/* Calculate value relative to current assembly position */
|
||||
/* Calculate relative value as integer */
|
||||
dist = rel_prevbc->offset + rel_prevbc->len;
|
||||
if (dist < bc->offset) {
|
||||
outval = yasm_intnum_create_uint(bc->offset - dist);
|
||||
yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
|
||||
} else {
|
||||
dist -= bc->offset;
|
||||
outval = yasm_intnum_create_uint(dist);
|
||||
if (value->curpos_rel) {
|
||||
/* PC-relative */
|
||||
if (!bc)
|
||||
return NULL; /* Can't calculate PC-relative value */
|
||||
if (rel_prevbc->section != bc->section)
|
||||
return NULL; /* not in this section */
|
||||
|
||||
if (dist < bc->offset) {
|
||||
outval = yasm_intnum_create_uint(bc->offset - dist);
|
||||
yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
|
||||
} else {
|
||||
dist -= bc->offset;
|
||||
outval = yasm_intnum_create_uint(dist);
|
||||
}
|
||||
}
|
||||
|
||||
if (value->rshift > 0) {
|
||||
|
|
|
|||
|
|
@ -100,15 +100,15 @@ int yasm_value_finalize_expr(/*@out@*/ yasm_value *value,
|
|||
/*@null@*/ /*@kept@*/ yasm_expr *e,
|
||||
unsigned int size);
|
||||
|
||||
/** Get value if absolute or PC-relative section-local relative. Returns NULL
|
||||
* otherwise.
|
||||
/** Get value if absolute, pure relative, or PC-relative section-local
|
||||
* relative. Returns NULL otherwise.
|
||||
* \param value value
|
||||
* \param bc current bytecode (for PC-relative calculation); if
|
||||
* NULL, NULL is returned for PC-relative values.
|
||||
* \param calc_bc_dist if nonzero, calculates bytecode distances in absolute
|
||||
* portion of value
|
||||
* \note Adds in value.rel (correctly) if PC-relative and in the same section
|
||||
* as bc (and there is no WRT or SEG).
|
||||
* as bc (and there is no WRT or SEG), or if value is pure-relative.
|
||||
* \return Intnum if can be resolved to integer value, otherwise NULL.
|
||||
*/
|
||||
/*@null@*/ /*@only@*/ yasm_intnum *yasm_value_get_intnum
|
||||
|
|
|
|||
|
|
@ -47,12 +47,6 @@ cdef extern from "libyasm/bytecode.h":
|
|||
cdef struct yasm_dataval
|
||||
cdef struct yasm_datavalhead
|
||||
|
||||
cdef enum yasm_bc_resolve_flags:
|
||||
YASM_BC_RESOLVE_NONE
|
||||
YASM_BC_RESOLVE_ERROR
|
||||
YASM_BC_RESOLVE_MIN_LEN
|
||||
YASM_BC_RESOLVE_UNKNOWN_LEN
|
||||
|
||||
cdef yasm_immval* yasm_imm_create_expr(yasm_expr *e)
|
||||
cdef yasm_expr* yasm_ea_get_disp(yasm_effaddr *ea)
|
||||
cdef void yasm_ea_set_len(yasm_effaddr *ea, unsigned int len)
|
||||
|
|
@ -118,6 +112,11 @@ cdef extern from "libyasm/bytecode.h":
|
|||
int indent_level)
|
||||
|
||||
cdef extern from "libyasm/bc-int.h":
|
||||
cdef enum yasm_bc_special:
|
||||
YASM_BC_SPECIAL_NONE
|
||||
YASM_BC_SPECIAL_RESERVE
|
||||
YASM_BC_SPECIAL_OFFSET
|
||||
|
||||
cdef struct yasm_bytecode_callback:
|
||||
void (*destroy) (void *contents)
|
||||
void (*c_print "print") (void *contents, FILE *f, int indent_level)
|
||||
|
|
@ -129,7 +128,7 @@ cdef extern from "libyasm/bc-int.h":
|
|||
int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, void *d,
|
||||
yasm_output_value_func output_value,
|
||||
yasm_output_reloc_func output_reloc)
|
||||
int reserve
|
||||
yasm_bc_special special
|
||||
|
||||
cdef struct yasm_bytecode:
|
||||
yasm_bytecode_callback *callback
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue