1 /* pkl-asm.h - Macro-assembler for the poke compiler.  */
2 
3 /* Copyright (C) 2019, 2020, 2021 Jose E. Marchesi */
4 
5 /* This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef PKL_ASM_H
20 #define PKL_ASM_H
21 
22 #include <config.h>
23 #include <stdarg.h>
24 
25 #include "pkl.h" /* For pkl_compiler */
26 #include "pkl-ast.h"
27 #include "ios.h" /* For IOS_NENC_* and IOS_ENDIAN_* */
28 #include "pvm.h"
29 
30 /* The macro-assembler provides constants, enumerations, C macros and
31    functions to make it easier to program the Poke Virtual
32    Machine.  */
33 
34 /* The user of the assembler refers to specific instructions using the
35    PKL_INSN_* symbols defined below.  See the file pkl-insn.def for
36    detailed information on the supported instructions.  */
37 
38 enum pkl_asm_insn
39 {
40 #define PKL_DEF_INSN(SYM, ARGS, NAME) SYM,
41 #  include "pkl-insn.def"
42 #undef PKL_DEF_INSN
43 };
44 
45 /* The following values are intended to be used as arguments to
46    PKL_INSN_PEEK instructions.  */
47 
48 #define PKL_ASM_ENDIAN_LSB IOS_ENDIAN_LSB
49 #define PKL_ASM_ENDIAN_MSB IOS_ENDIAN_MSB
50 #define PKL_ASM_NENC_1 IOS_NENC_1
51 #define PKL_ASM_NENC_2 IOS_NENC_2
52 
53 /* Enumeration with machine registers. */
54 
55 enum pkl_asm_reg
56 {
57  PKL_REG_FOO,
58  /* XXX: fill me.  */
59 };
60 
61 /* Opaque data structure for an assembler instance.  The struct is
62    defined in pkl-asm.c.  */
63 
64 typedef struct pkl_asm *pkl_asm;
65 
66 /* Create a new instance of an assembler.  This initializes a new
67    PVM program.  */
68 
69 pkl_asm pkl_asm_new (pkl_ast ast, pkl_compiler compiler,
70                      int prologue);
71 
72 /* Finish the assembly of the current program and return it.  This
73    function frees all resources used by the assembler instance, and
74    `pkl_asm_new' should be called again in order to assemble another
75    program.  */
76 
77 pvm_program pkl_asm_finish (pkl_asm pasm, int epilogue);
78 
79 /* Assemble an instruction INSN and append it to the program being
80    assembled in PASM.  If the instruction takes any argument, they
81    follow after INSN.  */
82 
83 void pkl_asm_insn (pkl_asm pasm, enum pkl_asm_insn insn, ...);
84 
85 /* Emit assembly code for calling the function FUNCNAME, which should
86    be defined in the global environment.  */
87 
88 void pkl_asm_call (pkl_asm pasm, const char *funcname);
89 
90 /* Conditionals.
91  *
92  *  pkl_asm_if (pasm, exp);
93  *
94  *  ... exp ...
95  *
96  *  pkl_asm_then (pasm);
97  *
98  *  ... whatever ...
99  *
100  *  pkl_asm_else (pasm);
101  *
102  *  ... whatever ...
103  *
104  *  pkl_asm_endif (pasm);
105  *
106  * Note that the condition expression EXP can be of any integral type.
107  * The macro-assembler will generate the right code for the specific
108  * type.
109  */
110 
111 void pkl_asm_if (pkl_asm pasm, pkl_ast_node exp);
112 
113 void pkl_asm_then (pkl_asm pasm);
114 
115 void pkl_asm_else (pkl_asm pasm);
116 
117 void pkl_asm_endif (pkl_asm pasm);
118 
119 /* Simple loops.
120  *
121  * pkl_asm_loop (pasm);
122  *
123  *   ... loop body ...
124  *
125  * pkl_asm_endloop (pasm);
126  */
127 
128 void pkl_asm_loop (pkl_asm pasm);
129 
130 void pkl_asm_endloop (pkl_asm pasm);
131 
132 /* While loops.
133  *
134  * pkl_asm_while (pasm);
135  *
136  *   ... condition ...
137  *
138  * pkl_asm_while_loop (pasm);
139  *
140  *   ... loop body ...
141  *
142  * pkl_asm_while_endloop (pasm);
143  *
144  * Note that the code in `... condition ...' should result in an
145  * int<32> value, and this is assumed by pkl_asm_while_loop.
146  */
147 
148 void pkl_asm_while (pkl_asm pasm);
149 
150 void pkl_asm_while_loop (pkl_asm pasm);
151 
152 void pkl_asm_while_endloop (pkl_asm pasm);
153 
154 /* For loops.
155  *
156  * pkl_asm_for (pasm);
157  *
158  * ... head ...
159  *
160  * pkl_asm_for_condition (pasm);
161  *
162  * ... condition ...
163  *
164  * pkl_asm_for_loop (pasm);
165  *
166  * ... body ...
167  *
168  * pkl_asm_for_tail (pasm);
169  *
170  * ... tail ...
171  *
172  * pkl_asm_for_endloop (pasm);
173  */
174 
175 void pkl_asm_for (pkl_asm pasm, pkl_ast_node head);
176 void pkl_asm_for_condition (pkl_asm pasm);
177 void pkl_asm_for_loop (pkl_asm pasm);
178 void pkl_asm_for_tail (pkl_asm pasm);
179 void pkl_asm_for_endloop (pkl_asm pasm);
180 
181 /* For-in-where loops.
182  *
183  * pkl_asm_for_in (pasm, container_type, selector)
184  *
185  * ... container ...
186  *
187  * pkl_asm_for_in_where (pasm);
188  *
189  * ... selector ...
190  *
191  * pkl_asm_for_in_loop (pasm);
192  *
193  * ... body ...
194  *
195  * pkl_asm_for_in_endloop (pasm);
196  *
197  * Note that the SELECTOR expression can be of any integral type. The
198  * macro-assembler will generate the right code for the specific type.
199  */
200 
201 void pkl_asm_for_in (pkl_asm pasm, int container_type,
202                      pkl_ast_node selector);
203 
204 void pkl_asm_for_in_where (pkl_asm pasm);
205 
206 void pkl_asm_for_in_loop (pkl_asm pasm);
207 
208 void pkl_asm_for_in_endloop (pkl_asm pasm);
209 
210 /* Try-catch blocks.
211  *
212  * pkl_asm_try (pasm);
213  *
214  * ... stmt ...
215  *
216  * pkl_asm_catch (pasm);
217  *
218  * ... stmt ...
219  *
220  * pkl_asm_endtry (pasm);
221  */
222 
223 void pkl_asm_try (pkl_asm pasm, pkl_ast_node type);
224 
225 void pkl_asm_catch (pkl_asm pasm);
226 
227 void pkl_asm_endtry (pkl_asm pasm);
228 
229 /* The following function returns the label associated to the
230    enclosing break-able construction (such as a loop or a switch).  If
231    there is not such enclosing environment, this function aborts.  */
232 
233 pvm_program_label pkl_asm_break_label (pkl_asm pasm);
234 
235 /* The following function returns the label associated to the
236    enclosing continuable construction (such as a loop).  If there is
237    not such enclosing environment, this function aborts.  */
238 
239 pvm_program_label pkl_asm_continue_label (pkl_asm pasm);
240 
241 /* Assembler directives:
242  *
243  * pkl_asm_note (pasm, STR);
244  * pkl_asm_loc (pasm, LOC);
245  *
246  * XXX: how to use pretty-printers in jitter in order to print
247  * directives like:
248  *
249  * .note "foobar"      Does nothing.
250  * .loc lb,le,cb,ce    Updates the current location in the PVM.
251  *                     Used for debugging and error reporting.
252  *
253  * instead of using instructions like:
254  *
255  *       note "foobar"
256  *       loc lb,le,cb,ce
257  */
258 
259 void pkl_asm_note (pkl_asm pasm, const char *str);
260 
261 /* Allocate a fresh PVM label and return it.  */
262 pvm_program_label pkl_asm_fresh_label (pkl_asm pasm);
263 
264 /* Append a label.  */
265 void pkl_asm_label (pkl_asm pasm, pvm_program_label label);
266 
267 #endif /* PKL_ASM_H */
268