yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
-static yasm_bc_resolve_flags bc_leb128_resolve
- (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+ static void bc_leb128_destroy(void *contents);
+ static void bc_leb128_print(const void *contents, FILE *f, int indent_level);
+ static void bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
++static int bc_leb128_calc_len
++ (yasm_bytecode *bc, /*@out@*/ unsigned long *long_len,
++ /*@out@*/ /*@only@*/ yasm_expr **critical, /*@out@*/ long *neg_thres,
++ /*@out@*/ long *pos_thres);
+ static int bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_expr_func output_expr,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
static void bc_reserve_destroy(void *contents);
static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
-static yasm_bc_resolve_flags bc_reserve_resolve
- (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int bc_reserve_calc_len
+ (yasm_bytecode *bc, /*@out@*/ unsigned long *long_len,
+ /*@out@*/ /*@only@*/ yasm_expr **critical, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
bc_data_tobytes
};
- bc_leb128_resolve,
+ static const yasm_bytecode_callback bc_leb128_callback = {
+ bc_leb128_destroy,
+ bc_leb128_print,
+ bc_leb128_finalize,
++ bc_leb128_calc_len,
++ yasm_bc_set_long_common,
+ bc_leb128_tobytes
+ };
+
static const yasm_bytecode_callback bc_reserve_callback = {
bc_reserve_destroy,
bc_reserve_print,
bc->len += slen*bc_data->size;
break;
}
+ if (bc_data->append_zero)
+ bc->len++;
}
- return YASM_BC_RESOLVE_MIN_LEN;
+ return 0;
}
static int
return yasm_bc_create_common(&bc_data_callback, data, line);
}
-static yasm_bc_resolve_flags
-bc_leb128_resolve(yasm_bytecode *bc, int save,
- yasm_calc_bc_dist_func calc_bc_dist)
+ static void
+ bc_leb128_destroy(void *contents)
+ {
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)contents;
+ yasm_dvs_destroy(&bc_leb128->datahead);
+ yasm_xfree(contents);
+ }
+
+ static void
+ bc_leb128_print(const void *contents, FILE *f, int indent_level)
+ {
+ const bytecode_leb128 *bc_leb128 = (const bytecode_leb128 *)contents;
+ fprintf(f, "%*s_Data_\n", indent_level, "");
+ fprintf(f, "%*sSign=%u\n", indent_level+1, "",
+ (unsigned int)bc_leb128->sign);
+ fprintf(f, "%*sElements:\n", indent_level+1, "");
+ yasm_dvs_print(&bc_leb128->datahead, f, indent_level+2);
+ }
+
+ static void
+ bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+ {
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
+ yasm_dataval *dv;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+
+ /* Only constant expressions are allowed.
+ * Because of this, go ahead and calculate length.
+ */
+ bc_leb128->len = 0;
+ STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_EXPR:
+ intn = yasm_expr_get_intnum(&dv->data.expn, NULL);
+ if (!intn) {
+ yasm__error(bc->line,
+ N_("LEB128 requires constant values"));
+ return;
+ }
+ /* Warn for negative values in unsigned environment.
+ * This could be an error instead: the likelihood this is
+ * desired is very low!
+ */
+ if (yasm_intnum_sign(intn) == -1 && !bc_leb128->sign)
+ yasm__warning(YASM_WARN_GENERAL, bc->line,
+ N_("negative value in unsigned LEB128"));
+ bc_leb128->len +=
+ yasm_intnum_size_leb128(intn, bc_leb128->sign);
+ break;
+ case DV_STRING:
+ yasm__error(bc->line,
+ N_("LEB128 does not allow string constants"));
+ return;
+ }
+ }
+ }
+
- return YASM_BC_RESOLVE_MIN_LEN;
++static int
++bc_leb128_calc_len(yasm_bytecode *bc, unsigned long *long_len,
++ yasm_expr **critical, long *neg_thres, long *pos_thres)
+ {
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
+ bc->len += bc_leb128->len;
++ return 0;
+ }
+
+ static int
+ bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_expr_func output_expr,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+ {
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
+ yasm_dataval *dv;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+
+ STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_EXPR:
+ intn = yasm_expr_get_intnum(&dv->data.expn, NULL);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in leb128_tobytes"));
+ *bufp += yasm_intnum_get_leb128(intn, *bufp, bc_leb128->sign);
+ break;
+ case DV_STRING:
+ yasm_internal_error(N_("string in leb128_tobytes"));
+ }
+ }
+
+ return 0;
+ }
+
+ yasm_bytecode *
+ yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
+ {
+ bytecode_leb128 *leb128 = yasm_xmalloc(sizeof(bytecode_leb128));
+
+ leb128->datahead = *datahead;
+ leb128->sign = sign;
+
+ return yasm_bc_create_common(&bc_leb128_callback, leb128, line);
+ }
+
static void
bc_reserve_destroy(void *contents)
{
if (!bc->callback)
yasm_internal_error(N_("got empty bytecode in bc_resolve"));
else
- retval = bc->callback->resolve(bc, save, calc_bc_dist);
+ retval = bc->callback->calc_len(bc, long_len, critical, neg_thres,
+ pos_thres);
- /* Multiply len by number of multiples */
+ /* Check for multiples */
if (bc->multiple) {
- /*@null@*/ yasm_expr *temp;
- if (save) {
- temp = NULL;
- tempp = &bc->multiple;
- } else {
- temp = yasm_expr_copy(bc->multiple);
- assert(temp != NULL);
- tempp = &temp;
- }
- num = yasm_expr_get_intnum(tempp, calc_bc_dist);
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ num = yasm_expr_get_intnum(&bc->multiple, NULL);
if (!num) {
- retval = YASM_BC_RESOLVE_UNKNOWN_LEN;
- if (temp && yasm_expr__contains(temp, YASM_EXPR_FLOAT)) {
+ if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
yasm__error(bc->line,
N_("expression must not contain floating point value"));
- retval |= YASM_BC_RESOLVE_ERROR;
+ retval = -1;
+ } else {
+ /* FIXME: Non-constant currently not allowed. */
+ yasm__error(bc->line,
+ N_("attempt to use non-constant multiple"));
+ retval = -1;
}
- } else {
- if (yasm_intnum_sign(num) >= 0)
- bc->len *= yasm_intnum_get_uint(num);
- else
- retval |= YASM_BC_RESOLVE_ERROR;
}
- yasm_expr_destroy(temp);
}
/* If we got an error somewhere along the line, clear out any calc len */