-
Notifications
You must be signed in to change notification settings - Fork 138
/
bytecode.c
256 lines (190 loc) · 6.76 KB
/
bytecode.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
Copyright (C) 2010-2011, Parrot Foundation.
=head1 NAME
src/embed/bytecode.c - Interface routines for working with Bytecode
=head1 DESCRIPTION
This file implements functions of the Parrot embedding interface dealing
with Parrot bytecode.
=head2 Functions
=over 4
=cut
*/
#include "parrot/parrot.h"
#include "parrot/runcore_api.h"
#include "parrot/api.h"
#include "embed_private.h"
/* HEADERIZER HFILE: include/parrot/api.h */
/*
=item C<Parrot_Int Parrot_api_load_bytecode_file(Parrot_PMC interp_pmc,
Parrot_String filename, Parrot_PMC * pbc)>
Load a bytecode file and stores the resulting bytecode in C<pbc>. This function
returns a true value if this call is successful and false value otherwise.
=cut
*/
/* TODO: This only works with the inital bytecode. After this we should use
Parrot_append_bytecode or something similar */
PARROT_API
Parrot_Int
Parrot_api_load_bytecode_file(Parrot_PMC interp_pmc,
ARGIN(Parrot_String filename), ARGOUT(Parrot_PMC * pbc))
{
ASSERT_ARGS(Parrot_api_load_bytecode_file)
EMBED_API_CALLIN(interp_pmc, interp)
PackFile * const pf = Parrot_pf_read_pbc_file(interp, filename);
*pbc = Parrot_pf_get_packfile_pmc(interp, pf, filename);
EMBED_API_CALLOUT(interp_pmc, interp)
}
/*
=item C<Parrot_Int Parrot_api_load_bytecode_bytes(Parrot_PMC interp_pmc, const
unsigned char * const pbc, Parrot_Int bytecode_size, Parrot_PMC * pbcpmc)>
Unpacks a bytecode from a buffer C<pbc> of a C<bytecode_size> size, and stores
the resulting bytecode in C<pbcpmc>. This function returns a true value if this
call is successful and false value otherwise.
=cut
*/
PARROT_API
Parrot_Int
Parrot_api_load_bytecode_bytes(Parrot_PMC interp_pmc,
ARGIN(const unsigned char * const pbc), Parrot_Int bytecode_size,
ARGOUT(Parrot_PMC * pbcpmc))
{
ASSERT_ARGS(Parrot_api_load_bytecode_bytes)
EMBED_API_CALLIN(interp_pmc, interp)
PackFile * const pf = PackFile_new(interp, 0);
PARROT_ASSERT(pf);
Parrot_block_GC_mark(interp);
if (!PackFile_unpack(interp, pf, (const opcode_t *)pbc, bytecode_size)) {
Parrot_unblock_GC_mark(interp);
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
"Could not unpack packfile");
}
*pbcpmc = Parrot_pf_get_packfile_pmc(interp, pf, STRINGNULL);
Parrot_unblock_GC_mark(interp);
EMBED_API_CALLOUT(interp_pmc, interp);
}
/* Load the bytecode into the interpreter, but don't execute it */
/* TODO: This only works with the inital bytecode. After this we should use
Parrot_append_bytecode or something similar */
/*
=item C<Parrot_Int Parrot_api_ready_bytecode(Parrot_PMC interp_pmc, Parrot_PMC
pbc, Parrot_PMC *main_sub)>
Prepares the bytecode C<pbc> to be run and stores the entry point subroutine in
C<main_sub>. This function returns a true value if this call is successful and
false value otherwise.
=cut
*/
PARROT_API
Parrot_Int
Parrot_api_ready_bytecode(Parrot_PMC interp_pmc, Parrot_PMC pbc,
ARGOUT(Parrot_PMC *main_sub))
{
ASSERT_ARGS(Parrot_api_ready_bytecode)
EMBED_API_CALLIN(interp_pmc, interp)
PackFile * const pf = (PackFile *)VTABLE_get_pointer(interp, pbc);
/* Debugging mode nonsense. */
if (Interp_debug_TEST(interp, PARROT_START_DEBUG_FLAG)) {
Parrot_io_eprintf(interp, "*** Parrot VM: %Ss core ***\n",
interp->run_core->name);
}
if (!pf)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNEXPECTED_NULL,
"Could not get packfile.");
if (pf->cur_cs)
Parrot_pf_set_current_packfile(interp, pbc);
Parrot_pf_prepare_packfile_init(interp, pbc);
*main_sub = Parrot_pf_get_packfile_main_sub(interp, pbc);
EMBED_API_CALLOUT(interp_pmc, interp)
}
/*
=item C<Parrot_Int Parrot_api_run_bytecode(Parrot_PMC interp_pmc, Parrot_PMC
pbc, Parrot_PMC args)>
Runs the bytecode C<pbc> passing optional C<args> parameters. This function
returns a true value if this call is successful and false value otherwise.
=cut
*/
PARROT_API
Parrot_Int
Parrot_api_run_bytecode(Parrot_PMC interp_pmc, Parrot_PMC pbc,
Parrot_PMC args)
{
ASSERT_ARGS(Parrot_api_run_bytecode)
EMBED_API_CALLIN(interp_pmc, interp)
Parrot_PMC _args = args ? args : PMCNULL;
/* Print out information if we are debugging */
if (Interp_debug_TEST(interp, PARROT_START_DEBUG_FLAG)) {
Parrot_io_eprintf(interp, "*** Parrot VM: %Ss core ***\n",
interp->run_core->name);
}
Parrot_pf_execute_bytecode_program(interp, pbc, _args);
EMBED_API_CALLOUT(interp_pmc, interp)
}
/*
=item C<Parrot_Int Parrot_api_disassemble_bytecode(Parrot_PMC interp_pmc,
Parrot_PMC pbc, const char * const outfile, Parrot_Int opts)>
Disassembles and prints out the C<pbc> bytecode. This function returns a true
value if this call is successful and false value otherwise.
=cut
*/
PARROT_API
Parrot_Int
Parrot_api_disassemble_bytecode(Parrot_PMC interp_pmc, Parrot_PMC pbc,
ARGIN_NULLOK(const char * const outfile), Parrot_Int opts)
{
ASSERT_ARGS(Parrot_api_disassemble_bytecode)
EMBED_API_CALLIN(interp_pmc, interp)
PackFile * const pf = (PackFile *)VTABLE_get_pointer(interp, pbc);
if (!pf)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNEXPECTED_NULL,
"Could not get packfile.");
if (pf->cur_cs)
Parrot_pf_set_current_packfile(interp, pbc);
Parrot_disassemble(interp, outfile, (Parrot_disassemble_options)opts);
EMBED_API_CALLOUT(interp_pmc, interp);
}
/*
=item C<Parrot_Int Parrot_api_serialize_bytecode_pmc(Parrot_PMC interp_pmc,
Parrot_PMC pbc, Parrot_String * bc)>
Serialize a packfile PMC into a sequence of bytes suitable for writing out
to a .pbc file
=cut
*/
PARROT_API
Parrot_Int
Parrot_api_serialize_bytecode_pmc(Parrot_PMC interp_pmc, Parrot_PMC pbc,
ARGOUT(Parrot_String * bc))
{
ASSERT_ARGS(Parrot_api_serialize_bytecode_pmc)
EMBED_API_CALLIN(interp_pmc, interp)
PackFile * const pf = (PackFile *)VTABLE_get_pointer(interp, pbc);
if (!pf)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNEXPECTED_NULL,
"Could not get packfile.");
*bc = Parrot_pf_serialize(interp, pf);
EMBED_API_CALLOUT(interp_pmc, interp)
}
/*
=item C<Parrot_Int Parrot_api_write_bytecode_to_file(Parrot_PMC interp_pmc,
Parrot_PMC pbc, Parrot_String filename)>
Write out a PackFile PMC to a .pbc file
=cut
*/
PARROT_API
Parrot_Int
Parrot_api_write_bytecode_to_file(Parrot_PMC interp_pmc, Parrot_PMC pbc,
Parrot_String filename)
{
ASSERT_ARGS(Parrot_api_write_bytecode_to_file)
EMBED_API_CALLIN(interp_pmc, interp)
Parrot_pf_write_pbc_file(interp, pbc, filename);
EMBED_API_CALLOUT(interp_pmc, interp)
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/