1/*
2 * Bytecode 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
29#include "libyasm-stdint.h"
30#include "coretype.h"
31
32#include "errwarn.h"
33#include "intnum.h"
34#include "expr.h"
35#include "value.h"
36
37#include "bytecode.h"
38
39
40typedef struct bytecode_reserve {
41    /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */
42    unsigned int itemsize;          /* size of each item (in bytes) */
43} bytecode_reserve;
44
45static void bc_reserve_destroy(void *contents);
46static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
47static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
48static int bc_reserve_elem_size(yasm_bytecode *bc);
49static int bc_reserve_calc_len(yasm_bytecode *bc,
50                               yasm_bc_add_span_func add_span,
51                               void *add_span_data);
52static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
53                              unsigned char *bufstart, void *d,
54                              yasm_output_value_func output_value,
55                              /*@null@*/ yasm_output_reloc_func output_reloc);
56
57static const yasm_bytecode_callback bc_reserve_callback = {
58    bc_reserve_destroy,
59    bc_reserve_print,
60    bc_reserve_finalize,
61    bc_reserve_elem_size,
62    bc_reserve_calc_len,
63    yasm_bc_expand_common,
64    bc_reserve_tobytes,
65    YASM_BC_SPECIAL_RESERVE
66};
67
68
69static void
70bc_reserve_destroy(void *contents)
71{
72    bytecode_reserve *reserve = (bytecode_reserve *)contents;
73    yasm_expr_destroy(reserve->numitems);
74    yasm_xfree(contents);
75}
76
77static void
78bc_reserve_print(const void *contents, FILE *f, int indent_level)
79{
80    const bytecode_reserve *reserve = (const bytecode_reserve *)contents;
81    fprintf(f, "%*s_Reserve_\n", indent_level, "");
82    fprintf(f, "%*sNum Items=", indent_level, "");
83    yasm_expr_print(reserve->numitems, f);
84    fprintf(f, "\n%*sItem Size=%u\n", indent_level, "", reserve->itemsize);
85}
86
87static void
88bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
89{
90    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
91    /* multiply reserve expression into multiple */
92    if (!bc->multiple)
93        bc->multiple = reserve->numitems;
94    else
95        bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL,
96                                             reserve->numitems, bc->line);
97    reserve->numitems = NULL;
98}
99
100static int
101bc_reserve_elem_size(yasm_bytecode *bc)
102{
103    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
104    return reserve->itemsize;
105}
106
107static int
108bc_reserve_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
109                    void *add_span_data)
110{
111    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
112    bc->len += reserve->itemsize;
113    return 0;
114}
115
116static int
117bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
118                   unsigned char *bufstart, void *d,
119                   yasm_output_value_func output_value,
120                   /*@unused@*/ yasm_output_reloc_func output_reloc)
121{
122    yasm_internal_error(N_("bc_reserve_tobytes called"));
123    /*@notreached@*/
124    return 1;
125}
126
127yasm_bytecode *
128yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
129                       unsigned long line)
130{
131    bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve));
132
133    /*@-mustfree@*/
134    reserve->numitems = numitems;
135    /*@=mustfree@*/
136    reserve->itemsize = itemsize;
137
138    return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
139}
140
141const yasm_expr *
142yasm_bc_reserve_numitems(yasm_bytecode *bc, unsigned int *itemsize)
143{
144    bytecode_reserve *reserve;
145
146    if (bc->callback != &bc_reserve_callback)
147        return NULL;
148
149    reserve = (bytecode_reserve *)bc->contents;
150    *itemsize = reserve->itemsize;
151    return reserve->numitems;
152}
153