qbe.c (5869B)
1 #include <assert.h> 2 #include <stdarg.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include "qbe.h" 7 #include "util.h" 8 9 // Simple type singletons 10 const struct qbe_type 11 qbe_byte = { 12 .stype = Q_BYTE, 13 .size = 1, 14 }, 15 qbe_half = { 16 .stype = Q_HALF, 17 .size = 2, 18 }, 19 qbe_word = { 20 .stype = Q_WORD, 21 .size = 4, 22 }, 23 qbe_long = { 24 .stype = Q_LONG, 25 .size = 8, 26 }, 27 qbe_single = { 28 .stype = Q_SINGLE, 29 .size = 4, 30 }, 31 qbe_double = { 32 .stype = Q_DOUBLE, 33 .size = 8, 34 }, 35 qbe_void = { 36 .stype = Q__VOID, 37 }, 38 qbe_aggregate = { 39 .stype = Q__AGGREGATE, 40 }; 41 42 const struct qbe_value variadic_sigil = {0}; 43 44 const char *qbe_instr[Q_LAST_INSTR] = { 45 [Q_ADD] = "add", 46 [Q_ALLOC16] = "alloc16", 47 [Q_ALLOC4] = "alloc4", 48 [Q_ALLOC8] = "alloc8", 49 [Q_AND] = "and", 50 [Q_BLIT] = "blit", 51 [Q_CALL] = "call", 52 [Q_CAST] = "cast", 53 [Q_CEQD] = "ceqd", 54 [Q_CEQL] = "ceql", 55 [Q_CEQS] = "ceqs", 56 [Q_CEQW] = "ceqw", 57 [Q_CGED] = "cged", 58 [Q_CGES] = "cges", 59 [Q_CGTD] = "cgtd", 60 [Q_CGTS] = "cgts", 61 [Q_CLED] = "cled", 62 [Q_CLES] = "cles", 63 [Q_CLTD] = "cltd", 64 [Q_CLTS] = "clts", 65 [Q_CNED] = "cned", 66 [Q_CNEL] = "cnel", 67 [Q_CNES] = "cnes", 68 [Q_CNEW] = "cnew", 69 [Q_COD] = "cod", 70 [Q_COPY] = "copy", 71 [Q_COS] = "cos", 72 [Q_CSGEL] = "csgel", 73 [Q_CSGEW] = "csgew", 74 [Q_CSGTL] = "csgtl", 75 [Q_CSGTW] = "csgtw", 76 [Q_CSLEL] = "cslel", 77 [Q_CSLEW] = "cslew", 78 [Q_CSLTL] = "csltl", 79 [Q_CSLTW] = "csltw", 80 [Q_CUGEL] = "cugel", 81 [Q_CUGEW] = "cugew", 82 [Q_CUGTL] = "cugtl", 83 [Q_CUGTW] = "cugtw", 84 [Q_CULEL] = "culel", 85 [Q_CULEW] = "culew", 86 [Q_CULTL] = "cultl", 87 [Q_CULTW] = "cultw", 88 [Q_CUOD] = "cuod", 89 [Q_CUOS] = "cuos", 90 [Q_DIV] = "div", 91 [Q_DTOSI] = "dtosi", 92 [Q_DTOUI] = "dtoui", 93 [Q_EXTS] = "exts", 94 [Q_EXTSB] = "extsb", 95 [Q_EXTSH] = "extsh", 96 [Q_EXTSW] = "extsw", 97 [Q_EXTUB] = "extub", 98 [Q_EXTUH] = "extuh", 99 [Q_EXTUW] = "extuw", 100 [Q_JMP] = "jmp", 101 [Q_JNZ] = "jnz", 102 [Q_LOADD] = "loadd", 103 [Q_LOADL] = "loadl", 104 [Q_LOADS] = "loads", 105 [Q_LOADSB] = "loadsb", 106 [Q_LOADSH] = "loadsh", 107 [Q_LOADSW] = "loadsw", 108 [Q_LOADUB] = "loadub", 109 [Q_LOADUH] = "loaduh", 110 [Q_LOADUW] = "loaduw", 111 [Q_MUL] = "mul", 112 [Q_NEG] = "neg", 113 [Q_OR] = "or", 114 [Q_REM] = "rem", 115 [Q_RET] = "ret", 116 [Q_SAR] = "sar", 117 [Q_SHL] = "shl", 118 [Q_SHR] = "shr", 119 [Q_SLTOF] = "sltof", 120 [Q_STOREB] = "storeb", 121 [Q_STORED] = "stored", 122 [Q_STOREH] = "storeh", 123 [Q_STOREL] = "storel", 124 [Q_STORES] = "stores", 125 [Q_STOREW] = "storew", 126 [Q_STOSI] = "stosi", 127 [Q_STOUI] = "stoui", 128 [Q_SUB] = "sub", 129 [Q_SWTOF] = "swtof", 130 [Q_TRUNCD] = "truncd", 131 [Q_UDIV] = "udiv", 132 [Q_ULTOF] = "ultof", 133 [Q_UREM] = "urem", 134 [Q_UWTOF] = "uwtof", 135 [Q_VAARG] = "vaarg", 136 [Q_VASTART] = "vastart", 137 [Q_XOR] = "xor", 138 }; 139 140 void 141 qbe_append_def(struct qbe_program *prog, struct qbe_def *def) 142 { 143 *prog->next = def; 144 prog->next = &def->next; 145 } 146 147 struct qbe_value * 148 qval_dup(const struct qbe_value *val) 149 { 150 struct qbe_value *new = xcalloc(1, sizeof(struct qbe_value)); 151 *new = *val; 152 if (val->kind != QV_CONST) { 153 new->name = xstrdup(val->name); 154 } 155 return new; 156 } 157 158 static void 159 va_geni(struct qbe_statement *stmt, enum qbe_instr instr, 160 const struct qbe_value *out, va_list ap) 161 { 162 stmt->type = Q_INSTR; 163 stmt->instr = instr; 164 165 if (out) { 166 stmt->out = qval_dup(out); 167 } 168 169 struct qbe_arguments **next = &stmt->args; 170 struct qbe_value *val; 171 while ((val = va_arg(ap, struct qbe_value *))) { 172 struct qbe_arguments *arg = xcalloc(1, sizeof(struct qbe_arguments)); 173 arg->value = *val; 174 *next = arg; 175 next = &arg->next; 176 } 177 } 178 179 void 180 geni(struct qbe_statement *stmt, const struct qbe_value *out, 181 enum qbe_instr instr, ...) 182 { 183 va_list ap; 184 va_start(ap, instr); 185 va_geni(stmt, instr, out, ap); 186 va_end(ap); 187 } 188 189 const char * 190 genl(struct qbe_statement *stmt, int *id, const char *fmt) 191 { 192 stmt->type = Q_LABEL; 193 int n = snprintf(NULL, 0, fmt, *id); 194 char *l = xcalloc(1, n + 1); 195 snprintf(l, n + 1, fmt, *id); 196 stmt->label = l; 197 *id = *id + 1; 198 return l; 199 } 200 201 void 202 push(struct qbe_statements *stmts, struct qbe_statement *stmt) 203 { 204 if (!stmts->stmts) { 205 stmts->sz = 256; 206 stmts->ln = 0; 207 stmts->stmts = xcalloc(1, 208 sizeof(struct qbe_statement) * stmts->sz); 209 } 210 if (stmts->ln + 1 >= stmts->sz) { 211 stmts->sz *= 2; 212 stmts->stmts = xrealloc(stmts->stmts, 213 sizeof(struct qbe_statement) * stmts->sz); 214 } 215 stmts->stmts[stmts->ln++] = *stmt; 216 } 217 218 void 219 pushi(struct qbe_func *func, const struct qbe_value *out, 220 enum qbe_instr instr, ...) 221 { 222 struct qbe_statement stmt = {0}; 223 va_list ap; 224 va_start(ap, instr); 225 226 struct qbe_value hack; 227 if (out && (out->type->stype == Q_BYTE || out->type->stype == Q_HALF)) { 228 hack = *out; 229 hack.type = &qbe_word; 230 out = &hack; 231 } 232 233 va_geni(&stmt, instr, out, ap); 234 va_end(ap); 235 push(&func->body, &stmt); 236 } 237 238 void 239 pushprei(struct qbe_func *func, const struct qbe_value *out, 240 enum qbe_instr instr, ...) 241 { 242 struct qbe_statement stmt = {0}; 243 va_list ap; 244 va_start(ap, instr); 245 va_geni(&stmt, instr, out, ap); 246 va_end(ap); 247 push(&func->prelude, &stmt); 248 } 249 250 const char * 251 pushl(struct qbe_func *func, int *id, const char *fmt) 252 { 253 struct qbe_statement stmt = {0}; 254 const char *l = genl(&stmt, id, fmt); 255 push(&func->body, &stmt); 256 return l; 257 } 258 259 void 260 pushc(struct qbe_func *func, const char *fmt, ...) 261 { 262 struct qbe_statement stmt = {0}; 263 264 va_list ap; 265 va_start(ap, fmt); 266 int n = vsnprintf(NULL, 0, fmt, ap); 267 va_end(ap); 268 269 char *str = xcalloc(1, n + 1); 270 va_start(ap, fmt); 271 vsnprintf(str, n + 1, fmt, ap); 272 va_end(ap); 273 274 stmt.comment = str; 275 push(&func->body, &stmt); 276 } 277 278 struct qbe_value 279 constl(uint64_t l) 280 { 281 return (struct qbe_value){ 282 .kind = QV_CONST, 283 .type = &qbe_long, 284 .lval = l, 285 }; 286 } 287 288 struct qbe_value 289 constw(uint32_t w) 290 { 291 return (struct qbe_value){ 292 .kind = QV_CONST, 293 .type = &qbe_word, 294 .wval = w, 295 }; 296 } 297 298 struct qbe_value 299 consts(float s) 300 { 301 return (struct qbe_value){ 302 .kind = QV_CONST, 303 .type = &qbe_single, 304 .sval = s, 305 }; 306 } 307 308 struct qbe_value 309 constd(double d) 310 { 311 return (struct qbe_value){ 312 .kind = QV_CONST, 313 .type = &qbe_double, 314 .dval = d, 315 }; 316 }