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