unsigned long len; /* total length of entire bytecode
(not including multiple copies) */
+ unsigned long mult_int; /* number of copies: integer version */
/* where it came from */
unsigned long line;
unsigned long offset; /* ~0UL if unknown */
unsigned long bc_index;
- /* optimizer info */
- unsigned long opt_flags;
-
/* NULL-terminated array of labels that point to this bytecode (as the
* bytecode previous to the label). NULL if no labels point here. */
/*@null@*/ yasm_symrec **symrecs;
bc->section = NULL;
bc->multiple = (yasm_expr *)NULL;
bc->len = 0;
+ bc->mult_int = 1;
bc->line = line;
bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
- bc->opt_flags = 0;
bc->symrecs = NULL;
bc->contents = contents;
/*@null@*/ yasm_intnum *
yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2)
{
- unsigned long dist;
+ unsigned long dist2, dist1;
yasm_intnum *intn;
if (precbc1->section != precbc2->section)
return NULL;
- dist = precbc2->offset + precbc2->len;
- if (dist < precbc1->offset + precbc1->len) {
- intn = yasm_intnum_create_uint(precbc1->offset + precbc1->len - dist);
+ dist1 = yasm_bc_next_offset(precbc1);
+ dist2 = yasm_bc_next_offset(precbc2);
+ if (dist2 < dist1) {
+ intn = yasm_intnum_create_uint(dist1 - dist2);
yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
return intn;
}
- dist -= precbc1->offset + precbc1->len;
- return yasm_intnum_create_uint(dist);
+ dist2 -= dist1;
+ return yasm_intnum_create_uint(dist2);
+}
+
+unsigned long
+yasm_bc_next_offset(yasm_bytecode *precbc)
+{
+ return precbc->offset + precbc->len*precbc->mult_int;
}
int
retval = bc->callback->calc_len(bc, add_span, add_span_data);
/* Check for multiples */
+ bc->mult_int = 1;
if (bc->multiple) {
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
num = yasm_expr_get_intnum(&bc->multiple, 0);
- if (num)
- bc->len *= yasm_intnum_get_uint(num);
- else {
+ if (num) {
+ if (yasm_intnum_sign(num) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+ retval = -1;
+ } else
+ bc->mult_int = 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"));
yasm_value value;
yasm_value_initialize(&value, bc->multiple, 0);
add_span(add_span_data, bc, 0, &value, 0, 0);
- bc->len = 0;
+ bc->mult_int = 0; /* assume 0 to start */
}
}
}
yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
/*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
{
- if (span == 0)
+ if (span == 0) {
yasm_internal_error(N_("cannot expand multiple yet"));
+
+ return 1;
+ }
if (!bc->callback) {
yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
/*@unreached@*/
- return 0;
+ return -1;
} else
return bc->callback->expand(bc, span, old_val, new_val, neg_thres,
pos_thres);
{
/*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
unsigned char *origbuf, *destbuf;
- unsigned long datasize, multiple, i;
+ unsigned long i;
int error = 0;
- if (yasm_bc_get_multiple(bc, &multiple, 1) || multiple == 0) {
+ if (yasm_bc_get_multiple(bc, &bc->mult_int, 1) || bc->mult_int == 0) {
*bufsize = 0;
return NULL;
}
/* special case for reserve bytecodes */
if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
- *bufsize = bc->len;
+ *bufsize = bc->len*bc->mult_int;
*gap = 1;
return NULL; /* we didn't allocate a buffer */
}
*gap = 0;
- if (*bufsize < bc->len) {
- mybuf = yasm_xmalloc(bc->len);
+ if (*bufsize < bc->len*bc->mult_int) {
+ mybuf = yasm_xmalloc(bc->len*bc->mult_int);
destbuf = mybuf;
} else
destbuf = buf;
- *bufsize = bc->len;
- datasize = bc->len / multiple;
+ *bufsize = bc->len*bc->mult_int;
if (!bc->callback)
yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
- else for (i=0; i<multiple; i++) {
+ else for (i=0; i<bc->mult_int; i++) {
origbuf = destbuf;
error = bc->callback->tobytes(bc, &destbuf, d, output_value,
output_reloc);
- if (!error && ((unsigned long)(destbuf - origbuf) != datasize))
+ if (!error && ((unsigned long)(destbuf - origbuf) != bc->len))
yasm_internal_error(
N_("written length does not match optimized length"));
}
/** Determine the distance between the starting offsets of two bytecodes.
* \param precbc1 preceding bytecode to the first bytecode
* \param precbc2 preceding bytecode to the second bytecode
+ * \caution Only valid /after/ optimization.
* \return Distance in bytes between the two bytecodes (bc2-bc1), or NULL if
* the distance was indeterminate.
*/
/*@null@*/ /*@only@*/ yasm_intnum *yasm_calc_bc_dist
(yasm_bytecode *precbc1, yasm_bytecode *precbc2);
+/** Get the offset of the next bytecode (the next bytecode doesn't have to
+ * actually exist).
+ * \caution Only valid /after/ optimization.
+ * \param precbc preceding bytecode
+ * \return Offset of the next bytecode in bytes.
+ */
+unsigned long yasm_bc_next_offset(yasm_bytecode *precbc);
+
/** Add a dependent span for a bytecode.
* \param add_span_data add_span_data passed into bc_calc_len()
* \param bc bytecode containing span
span->rel_term->subst = ~0U;
span->rel_term->cur_val = 0;
- span->rel_term->new_val =
- rel_precbc->offset + rel_precbc->len - span->bc->offset;
+ span->rel_term->new_val = yasm_bc_next_offset(rel_precbc) -
+ span->bc->offset;
}
}
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;
+ long pos_thres = (long)yasm_bc_next_offset(bc);
int retval = yasm_bc_expand(bc, 1, 0,
- (long)(prevbc->offset+prevbc->len),
+ (long)yasm_bc_next_offset(prevbc),
&neg_thres, &pos_thres);
yasm_errwarn_propagate(errwarns, bc->line);
if (retval < 0)
saw_error = 1;
}
bc->offset = offset;
- offset += bc->len;
+ offset += bc->len*bc->mult_int;
prevbc = bc;
bc = STAILQ_NEXT(bc, link);
}
else {
if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
span = create_span(bc, 1, NULL, SPECIAL_BC_OFFSET, 0,
- (long)(bc->offset+bc->len));
+ (long)yasm_bc_next_offset(bc));
TAILQ_INSERT_TAIL(&optd.spans, span, link);
if (bc->multiple) {
yasm_error_set(YASM_ERROR_VALUE,
}
}
- offset += bc->len;
+ offset += bc->len*bc->mult_int;
}
prevbc = bc;
if (span->rel_term) {
span->rel_term->cur_val = span->rel_term->new_val;
if (span->rel_term->precbc2)
- span->rel_term->new_val = span->rel_term->precbc2->offset
- + span->rel_term->precbc2->len - span->bc->offset;
+ span->rel_term->new_val =
+ yasm_bc_next_offset(span->rel_term->precbc2) -
+ span->bc->offset;
else
span->rel_term->new_val = span->bc->offset -
- (span->rel_term->precbc->offset +
- span->rel_term->precbc->len);
+ yasm_bc_next_offset(span->rel_term->precbc);
}
switch (span->special) {
* span values and thresholds.
*/
span->new_val = span->rel_term->new_val;
- span->pos_thres = (long)(span->bc->offset+span->bc->len);
+ span->pos_thres = (long)yasm_bc_next_offset(span->bc);
span->rel_term->cur_val = span->rel_term->new_val;
span->cur_val = span->new_val;
if (!recalc_normal_span(span))
continue;
- orig_len = span->bc->len;
+ orig_len = span->bc->len * span->bc->mult_int;
retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
span->new_val, &span->neg_thres,
} else
span->active = 0; /* we're done with this span */
- optd.len_diff = span->bc->len - orig_len;
+ optd.len_diff = span->bc->len * span->bc->mult_int - orig_len;
if (optd.len_diff == 0)
continue; /* didn't increase in size */
return NULL; /* not PC-relative */
/* Calculate value relative to current assembly position */
- dist = rel_prevbc->offset + rel_prevbc->len;
+ dist = yasm_bc_next_offset(rel_prevbc);
if (dist < bc->offset) {
outval = yasm_intnum_create_uint(bc->offset - dist);
yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
return 0; /* not PC-relative */
/* Calculate value relative to current assembly position */
- dist = rel_prevbc->offset + rel_prevbc->len;
+ dist = yasm_bc_next_offset(rel_prevbc);
if (dist < bc->offset) {
outval = yasm_intnum_create_uint(bc->offset - dist);
yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
yasm_cv__append_bc(yasm_section *sect, yasm_bytecode *bc)
{
yasm_bytecode *precbc = yasm_section_bcs_last(sect);
- bc->offset = precbc ? precbc->offset + precbc->len : 0;
+ bc->offset = yasm_bc_next_offset(precbc);
yasm_section_bcs_append(sect, bc);
return precbc;
}
/*@unused@*/ RCSID("$Id$");
#define YASM_LIB_INTERNAL
-#define YASM_BC_INTERNAL
#include <libyasm.h>
#include "dwarf2-dbgfmt.h"
yasm_dwarf2__append_bc(yasm_section *sect, yasm_bytecode *bc)
{
yasm_bytecode *precbc = yasm_section_bcs_last(sect);
- bc->offset = precbc ? precbc->offset + precbc->len : 0;
+ bc->offset = yasm_bc_next_offset(precbc);
yasm_section_bcs_append(sect, bc);
return precbc;
}
if (!state.precbc)
state.precbc = yasm_section_bcs_first(sect);
bc = yasm_section_bcs_last(sect);
- addr_delta = bc->offset + bc->len - state.precbc->offset;
+ addr_delta = yasm_bc_next_offset(bc) - state.precbc->offset;
if (addr_delta == DWARF2_MAX_SPECIAL_ADDR_DELTA)
dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_const_add_pc,
NULL);
static yasm_bytecode *
stabs_dbgfmt_append_bcstr(yasm_section *sect, const char *str)
{
- yasm_bytecode *bc, *precbc;
+ yasm_bytecode *bc;
- precbc = yasm_section_bcs_last(sect);
bc = yasm_bc_create_common(&stabs_bc_str_callback, yasm__xstrdup(str), 0);
bc->len = strlen(str)+1;
- bc->offset = precbc ? precbc->offset + precbc->len : 0;
+ bc->offset = yasm_bc_next_offset(yasm_section_bcs_last(sect));
yasm_section_bcs_append(sect, bc);
unsigned long desc, /*@null@*/ yasm_symrec *symvalue,
/*@null@*/ yasm_bytecode *bcvalue, unsigned long value)
{
- yasm_bytecode *bc, *precbc;
+ yasm_bytecode *bc;
stabs_stab *stab = yasm_xmalloc(sizeof(stabs_stab));
stab->other = 0;
stab->bcvalue = bcvalue;
stab->value = value;
- precbc = yasm_section_bcs_last(sect);
bc = yasm_bc_create_common(&stabs_bc_stab_callback, stab,
bcvalue ? bcvalue->line : 0);
bc->len = info->stablen;
- bc->offset = precbc ? precbc->offset + precbc->len : 0;
+ bc->offset = yasm_bc_next_offset(yasm_section_bcs_last(sect));
yasm_section_bcs_append(sect, bc);
stab->bcvalue = NULL;
stab->symvalue = NULL;
- stab->value = laststr->offset + laststr->len;
+ stab->value = yasm_bc_next_offset(laststr);
stab->bcstr = filebc;
stab->type = N_UNDF;
stab->other = 0;
/*@out@*/ unsigned long *prevsectlen,
/*@out@*/ unsigned long *padamt)
{
- /*@dependent@*/ /*@null@*/ yasm_bytecode *last;
unsigned long start;
unsigned long align;
/* Figure out the size of .text by looking at the last bytecode's offset
* plus its length. Add the start and size together to get the new start.
*/
- last = yasm_section_bcs_last(prevsect);
- if (last)
- *prevsectlen = last->offset + last->len;
- else
- *prevsectlen = 0;
+ *prevsectlen = yasm_bc_next_offset(yasm_section_bcs_last(prevsect));
start = base + *prevsectlen;
/* Round new start up to alignment of .data section, and adjust textlen to
{
/*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
/*@dependent@*/ /*@null@*/ coff_section_data *csd;
- /*@null@*/ yasm_bytecode *last;
/* Don't output absolute sections */
if (yasm_section_is_absolute(sect))
assert(csd != NULL);
csd->addr = info->addr;
- last = yasm_section_bcs_last(sect);
- if (last)
- info->addr += last->offset + last->len;
+ info->addr += yasm_bc_next_offset(yasm_section_bcs_last(sect));
return 0;
}
&coff_section_data_cb);
assert(sym_csd != NULL);
sym = sym_csd->sym;
- intn_val = sym_precbc->offset + sym_precbc->len;
+ intn_val = yasm_bc_next_offset(sym_precbc);
if (COFF_SET_VMA)
intn_val += sym_csd->addr;
}
* taken care of by special relocation types.
*/
if (objfmt_coff->win64 && value->ip_rel)
- intn_val += bc->len;
+ intn_val += bc->len*bc->mult_int;
else if (objfmt_coff->win32)
intn_val += offset+destsize;
else
}
if (!value->ip_rel)
reloc->type = COFF_RELOC_AMD64_REL32;
- else switch (bc->len - (offset+destsize)) {
+ else switch (bc->len*bc->mult_int - (offset+destsize)) {
case 0:
reloc->type = COFF_RELOC_AMD64_REL32;
break;
csd->addr = info->addr;
if ((csd->flags & COFF_STYP_STD_MASK) == COFF_STYP_BSS) {
- yasm_bytecode *last = yasm_section_bcs_last(sect);
-
/* Don't output BSS sections.
* TODO: Check for non-reserve bytecodes?
*/
pos = 0; /* position = 0 because it's not in the file */
- csd->size = last->offset + last->len;
+ csd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
} else {
- yasm_bytecode *last = yasm_section_bcs_last(sect);
-
pos = ftell(info->f);
if (pos == -1) {
yasm__fatal(N_("could not get file position on output file"));
coff_objfmt_output_bytecode);
/* Sanity check final section size */
- if (csd->size != (last->offset + last->len))
+ if (csd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect)))
yasm_internal_error(
N_("coff: section computed size did not match actual size"));
}
} else
yasm_internal_error(N_("didn't understand section"));
if (precbc)
- value += precbc->offset + precbc->len;
+ value += yasm_bc_next_offset(precbc);
}
} else if ((equ_val = yasm_symrec_get_equ(sym))) {
yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
}
if (precbc)
- value = precbc->offset + precbc->len;
+ value = yasm_bc_next_offset(precbc);
elf_symtab_set_nonzero(entry, sect, 0, 0, 0, NULL, &value);
return 0;
assert(sym_shead != NULL);
sym = elf_secthead_get_sym(sym_shead);
- intn_val = sym_precbc->offset + sym_precbc->len;
+ intn_val = yasm_bc_next_offset(sym_precbc);
}
}
yasm_bytecode *last = yasm_section_bcs_last(sect);
if (last) {
yasm_intnum *sectsize;
- sectsize = yasm_intnum_create_uint(last->offset + last->len);
+ sectsize = yasm_intnum_create_uint(yasm_bc_next_offset(last));
elf_secthead_add_size(shead, sectsize);
yasm_intnum_destroy(sectsize);
}
/*@dependent@*/ /*@null@*/ xdf_section_data *xsd;
long pos;
xdf_reloc *reloc;
- yasm_bytecode *last;
/* FIXME: Don't output absolute sections into the section table */
if (yasm_section_is_absolute(sect))
xsd = yasm_section_get_data(sect, &xdf_section_data_cb);
assert(xsd != NULL);
- last = yasm_section_bcs_last(sect);
if (xsd->flags & XDF_SECT_BSS) {
/* Don't output BSS sections.
* TODO: Check for non-reserve bytecodes?
*/
pos = 0; /* position = 0 because it's not in the file */
- xsd->size = last->offset + last->len;
+ xsd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
} else {
pos = ftell(info->f);
if (pos == -1) {
xdf_objfmt_output_bytecode);
/* Sanity check final section size */
- if (xsd->size != (last->offset + last->len))
+ if (xsd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect)))
yasm_internal_error(
N_("xdf: section computed size did not match actual size"));
}
} else
yasm_internal_error(N_("didn't understand section"));
if (precbc)
- value += precbc->offset + precbc->len;
+ value += yasm_bc_next_offset(precbc);
}
} else if ((equ_val = yasm_symrec_get_equ(sym))) {
yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
yasm_section *section
yasm_expr *multiple
unsigned long len
+ unsigned long mult_int
unsigned long line
unsigned long offset
- unsigned long opt_flags
+ unsigned long bc_index
yasm_symrec **symrecs
void *contents
property len:
def __get__(self): return self.bc.len
def __set__(self, value): self.bc.len = value
+ property mult_int:
+ def __get__(self): return self.bc.mult_int
+ def __set__(self, value): self.bc.mult_int = value
property line:
def __get__(self): return self.bc.line
def __set__(self, value): self.bc.line = value
property offset:
def __get__(self): return self.bc.offset
def __set__(self, value): self.bc.offset = value
- property opt_flags:
- def __get__(self): return self.bc.opt_flags
- def __set__(self, value): self.bc.opt_flags = value
+ property bc_index:
+ def __get__(self): return self.bc.bc_index
+ def __set__(self, value): self.bc.bc_index = value
property symbols:
# Someday extend this to do something modifiable, e.g. return a
# list-like object.