diff options
author | somov <somov@yandex-team.ru> | 2022-02-10 16:45:47 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:47 +0300 |
commit | a5950576e397b1909261050b8c7da16db58f10b1 (patch) | |
tree | 7ba7677f6a4c3e19e2cefab34d16df2c8963b4d4 /contrib/tools/yasm/libyasm/bytecode.c | |
parent | 81eddc8c0b55990194e112b02d127b87d54164a9 (diff) | |
download | ydb-a5950576e397b1909261050b8c7da16db58f10b1.tar.gz |
Restoring authorship annotation for <somov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/yasm/libyasm/bytecode.c')
-rw-r--r-- | contrib/tools/yasm/libyasm/bytecode.c | 772 |
1 files changed, 386 insertions, 386 deletions
diff --git a/contrib/tools/yasm/libyasm/bytecode.c b/contrib/tools/yasm/libyasm/bytecode.c index f864bae0aa..ee28c2b0d9 100644 --- a/contrib/tools/yasm/libyasm/bytecode.c +++ b/contrib/tools/yasm/libyasm/bytecode.c @@ -1,386 +1,386 @@ -/* - * Bytecode utility functions - * - * Copyright (C) 2001-2007 Peter Johnson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "util.h" - -#include "libyasm-stdint.h" -#include "coretype.h" - -#include "errwarn.h" -#include "intnum.h" -#include "expr.h" -#include "value.h" -#include "symrec.h" - -#include "bytecode.h" - - -void -yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e) -{ - if (bc->multiple) - bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e, - e->line); - else - bc->multiple = e; -} - -void -yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ -} - -int -yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span, - void *add_span_data) -{ - yasm_internal_error(N_("bytecode length cannot be calculated")); - /*@unreached@*/ - return 0; -} - -int -yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val, - /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) -{ - yasm_internal_error(N_("bytecode does not have any dependent spans")); - /*@unreached@*/ - return 0; -} - -int -yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf, - unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc) -{ - yasm_internal_error(N_("bytecode cannot be converted to bytes")); - /*@unreached@*/ - return 0; -} - -void -yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback, - void *contents) -{ - if (bc->callback) - bc->callback->destroy(bc->contents); - bc->callback = callback; - bc->contents = contents; -} - -yasm_bytecode * -yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents, - unsigned long line) -{ - yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode)); - - bc->callback = callback; - 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->symrecs = NULL; - bc->contents = contents; - - return bc; -} - -yasm_section * -yasm_bc_get_section(yasm_bytecode *bc) -{ - return bc->section; -} - -void -yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym) -{ - if (!bc->symrecs) { - bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *)); - bc->symrecs[0] = sym; - bc->symrecs[1] = NULL; - } else { - /* Very inefficient implementation for large numbers of symbols. But - * that would be very unusual, so use the simple algorithm instead. - */ - size_t count = 1; - while (bc->symrecs[count]) - count++; - bc->symrecs = yasm_xrealloc(bc->symrecs, - (count+2)*sizeof(yasm_symrec *)); - bc->symrecs[count] = sym; - bc->symrecs[count+1] = NULL; - } -} - -void -yasm_bc_destroy(yasm_bytecode *bc) -{ - if (!bc) - return; - - if (bc->callback) - bc->callback->destroy(bc->contents); - yasm_expr_destroy(bc->multiple); - if (bc->symrecs) - yasm_xfree(bc->symrecs); - yasm_xfree(bc); -} - -void -yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level) -{ - if (!bc->callback) - fprintf(f, "%*s_Empty_\n", indent_level, ""); - else - bc->callback->print(bc->contents, f, indent_level); - fprintf(f, "%*sMultiple=", indent_level, ""); - if (!bc->multiple) - fprintf(f, "nil (1)"); - else - yasm_expr_print(bc->multiple, f); - fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len); - fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line); - fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset); -} - -void -yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ - if (bc->callback) - bc->callback->finalize(bc, prev_bc); - if (bc->multiple) { - yasm_value val; - - if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0)) - yasm_error_set(YASM_ERROR_TOO_COMPLEX, - N_("multiple expression too complex")); - else if (val.rel) - yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, - N_("multiple expression not absolute")); - /* Finalize creates NULL output if value=0, but bc->multiple is NULL - * if value=1 (this difference is to make the common case small). - * However, this means we need to set bc->multiple explicitly to 0 - * here if val.abs is NULL. - */ - if (val.abs) - bc->multiple = val.abs; - else - bc->multiple = yasm_expr_create_ident( - yasm_expr_int(yasm_intnum_create_uint(0)), bc->line); - } -} - -/*@null@*/ yasm_intnum * -yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2) -{ - unsigned long dist2, dist1; - yasm_intnum *intn; - - if (precbc1->section != precbc2->section) - return NULL; - - 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; - } - 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 -yasm_bc_elem_size(yasm_bytecode *bc) -{ - if (!bc->callback) { - yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size")); - return 0; - } else if (!bc->callback->elem_size) - return 0; - else - return bc->callback->elem_size(bc); -} - -int -yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, - void *add_span_data) -{ - int retval = 0; - - bc->len = 0; - - if (!bc->callback) - yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len")); - else - 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) { - 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_int(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 { - yasm_value value; - yasm_value_initialize(&value, bc->multiple, 0); - add_span(add_span_data, bc, 0, &value, 0, 0); - bc->mult_int = 0; /* assume 0 to start */ - } - } - } - - /* If we got an error somewhere along the line, clear out any calc len */ - if (retval < 0) - bc->len = 0; - - return retval; -} - -int -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) { - bc->mult_int = new_val; - return 1; - } - if (!bc->callback) { - yasm_internal_error(N_("got empty bytecode in yasm_bc_expand")); - /*@unreached@*/ - return -1; - } else - return bc->callback->expand(bc, span, old_val, new_val, neg_thres, - pos_thres); -} - -/*@null@*/ /*@only@*/ unsigned char * -yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, - /*@out@*/ int *gap, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc) - /*@sets *buf@*/ -{ - /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL; - unsigned char *bufstart; - unsigned char *origbuf, *destbuf; - long i; - int error = 0; - - long mult; - if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) { - *bufsize = 0; - return NULL; - } - bc->mult_int = mult; - - /* special case for reserve bytecodes */ - if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) { - *bufsize = bc->len*bc->mult_int; - *gap = 1; - return NULL; /* we didn't allocate a buffer */ - } - *gap = 0; - - if (*bufsize < bc->len*bc->mult_int) { - mybuf = yasm_xmalloc(bc->len*bc->mult_int); - destbuf = mybuf; - } else - destbuf = buf; - bufstart = destbuf; - - *bufsize = bc->len*bc->mult_int; - - if (!bc->callback) - yasm_internal_error(N_("got empty bytecode in bc_tobytes")); - else for (i=0; i<bc->mult_int; i++) { - origbuf = destbuf; - error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value, - output_reloc); - - if (!error && ((unsigned long)(destbuf - origbuf) != bc->len)) - yasm_internal_error( - N_("written length does not match optimized length")); - } - - return mybuf; -} - -int -yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist) -{ - /*@dependent@*/ /*@null@*/ const yasm_intnum *num; - - *multiple = 1; - if (bc->multiple) { - num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist); - if (!num) { - yasm_error_set(YASM_ERROR_VALUE, - N_("could not determine multiple")); - return 1; - } - if (yasm_intnum_sign(num) < 0) { - yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative")); - return 1; - } - *multiple = yasm_intnum_get_int(num); - } - return 0; -} - -const yasm_expr * -yasm_bc_get_multiple_expr(const yasm_bytecode *bc) -{ - return bc->multiple; -} - -yasm_insn * -yasm_bc_get_insn(yasm_bytecode *bc) -{ - if (bc->callback->special != YASM_BC_SPECIAL_INSN) - return NULL; - return (yasm_insn *)bc->contents; -} +/* + * Bytecode utility functions + * + * Copyright (C) 2001-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "util.h" + +#include "libyasm-stdint.h" +#include "coretype.h" + +#include "errwarn.h" +#include "intnum.h" +#include "expr.h" +#include "value.h" +#include "symrec.h" + +#include "bytecode.h" + + +void +yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e) +{ + if (bc->multiple) + bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e, + e->line); + else + bc->multiple = e; +} + +void +yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ +} + +int +yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + yasm_internal_error(N_("bytecode length cannot be calculated")); + /*@unreached@*/ + return 0; +} + +int +yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val, + /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) +{ + yasm_internal_error(N_("bytecode does not have any dependent spans")); + /*@unreached@*/ + return 0; +} + +int +yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf, + unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc) +{ + yasm_internal_error(N_("bytecode cannot be converted to bytes")); + /*@unreached@*/ + return 0; +} + +void +yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback, + void *contents) +{ + if (bc->callback) + bc->callback->destroy(bc->contents); + bc->callback = callback; + bc->contents = contents; +} + +yasm_bytecode * +yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents, + unsigned long line) +{ + yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode)); + + bc->callback = callback; + 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->symrecs = NULL; + bc->contents = contents; + + return bc; +} + +yasm_section * +yasm_bc_get_section(yasm_bytecode *bc) +{ + return bc->section; +} + +void +yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym) +{ + if (!bc->symrecs) { + bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *)); + bc->symrecs[0] = sym; + bc->symrecs[1] = NULL; + } else { + /* Very inefficient implementation for large numbers of symbols. But + * that would be very unusual, so use the simple algorithm instead. + */ + size_t count = 1; + while (bc->symrecs[count]) + count++; + bc->symrecs = yasm_xrealloc(bc->symrecs, + (count+2)*sizeof(yasm_symrec *)); + bc->symrecs[count] = sym; + bc->symrecs[count+1] = NULL; + } +} + +void +yasm_bc_destroy(yasm_bytecode *bc) +{ + if (!bc) + return; + + if (bc->callback) + bc->callback->destroy(bc->contents); + yasm_expr_destroy(bc->multiple); + if (bc->symrecs) + yasm_xfree(bc->symrecs); + yasm_xfree(bc); +} + +void +yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level) +{ + if (!bc->callback) + fprintf(f, "%*s_Empty_\n", indent_level, ""); + else + bc->callback->print(bc->contents, f, indent_level); + fprintf(f, "%*sMultiple=", indent_level, ""); + if (!bc->multiple) + fprintf(f, "nil (1)"); + else + yasm_expr_print(bc->multiple, f); + fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len); + fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line); + fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset); +} + +void +yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ + if (bc->callback) + bc->callback->finalize(bc, prev_bc); + if (bc->multiple) { + yasm_value val; + + if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0)) + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("multiple expression too complex")); + else if (val.rel) + yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, + N_("multiple expression not absolute")); + /* Finalize creates NULL output if value=0, but bc->multiple is NULL + * if value=1 (this difference is to make the common case small). + * However, this means we need to set bc->multiple explicitly to 0 + * here if val.abs is NULL. + */ + if (val.abs) + bc->multiple = val.abs; + else + bc->multiple = yasm_expr_create_ident( + yasm_expr_int(yasm_intnum_create_uint(0)), bc->line); + } +} + +/*@null@*/ yasm_intnum * +yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2) +{ + unsigned long dist2, dist1; + yasm_intnum *intn; + + if (precbc1->section != precbc2->section) + return NULL; + + 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; + } + 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 +yasm_bc_elem_size(yasm_bytecode *bc) +{ + if (!bc->callback) { + yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size")); + return 0; + } else if (!bc->callback->elem_size) + return 0; + else + return bc->callback->elem_size(bc); +} + +int +yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + int retval = 0; + + bc->len = 0; + + if (!bc->callback) + yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len")); + else + 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) { + 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_int(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 { + yasm_value value; + yasm_value_initialize(&value, bc->multiple, 0); + add_span(add_span_data, bc, 0, &value, 0, 0); + bc->mult_int = 0; /* assume 0 to start */ + } + } + } + + /* If we got an error somewhere along the line, clear out any calc len */ + if (retval < 0) + bc->len = 0; + + return retval; +} + +int +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) { + bc->mult_int = new_val; + return 1; + } + if (!bc->callback) { + yasm_internal_error(N_("got empty bytecode in yasm_bc_expand")); + /*@unreached@*/ + return -1; + } else + return bc->callback->expand(bc, span, old_val, new_val, neg_thres, + pos_thres); +} + +/*@null@*/ /*@only@*/ unsigned char * +yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, + /*@out@*/ int *gap, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc) + /*@sets *buf@*/ +{ + /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL; + unsigned char *bufstart; + unsigned char *origbuf, *destbuf; + long i; + int error = 0; + + long mult; + if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) { + *bufsize = 0; + return NULL; + } + bc->mult_int = mult; + + /* special case for reserve bytecodes */ + if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) { + *bufsize = bc->len*bc->mult_int; + *gap = 1; + return NULL; /* we didn't allocate a buffer */ + } + *gap = 0; + + if (*bufsize < bc->len*bc->mult_int) { + mybuf = yasm_xmalloc(bc->len*bc->mult_int); + destbuf = mybuf; + } else + destbuf = buf; + bufstart = destbuf; + + *bufsize = bc->len*bc->mult_int; + + if (!bc->callback) + yasm_internal_error(N_("got empty bytecode in bc_tobytes")); + else for (i=0; i<bc->mult_int; i++) { + origbuf = destbuf; + error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value, + output_reloc); + + if (!error && ((unsigned long)(destbuf - origbuf) != bc->len)) + yasm_internal_error( + N_("written length does not match optimized length")); + } + + return mybuf; +} + +int +yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist) +{ + /*@dependent@*/ /*@null@*/ const yasm_intnum *num; + + *multiple = 1; + if (bc->multiple) { + num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist); + if (!num) { + yasm_error_set(YASM_ERROR_VALUE, + N_("could not determine multiple")); + return 1; + } + if (yasm_intnum_sign(num) < 0) { + yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative")); + return 1; + } + *multiple = yasm_intnum_get_int(num); + } + return 0; +} + +const yasm_expr * +yasm_bc_get_multiple_expr(const yasm_bytecode *bc) +{ + return bc->multiple; +} + +yasm_insn * +yasm_bc_get_insn(yasm_bytecode *bc) +{ + if (bc->callback->special != YASM_BC_SPECIAL_INSN) + return NULL; + return (yasm_insn *)bc->contents; +} |