asdl.c (9925B)
1 #include "c.h" 2 #include "rcc.h" 3 #if WIN32 4 #include <fcntl.h> 5 #include <io.h> 6 #endif 7 8 9 static list_ty interfaces; 10 static rcc_program_ty pickle; 11 12 char *string(const char *str) { 13 return (char *)Atom_string(str); 14 } 15 16 char *stringd(long n) { 17 return (char *)Atom_int(n); 18 } 19 20 char *stringn(const char *str, int len) { 21 return (char *)Atom_new(str, len); 22 } 23 24 static void put(rcc_interface_ty node) { 25 Seq_addhi(interfaces, node); 26 } 27 28 static int typeuid(Type ty) { 29 rcc_type_ty type; 30 31 assert(ty); 32 if (ty->x.typeno != 0) 33 return ty->x.typeno; 34 ty->x.typeno = pickle->nuids++; 35 switch (ty->op) { 36 #define xx(op) case op: type = rcc_##op(ty->size, ty->align); break 37 xx(INT); 38 xx(UNSIGNED); 39 xx(FLOAT); 40 xx(VOID); 41 #undef xx 42 #define xx(op) case op: type = rcc_##op(ty->size, ty->align, typeuid(ty->type)); break 43 xx(POINTER); 44 xx(ARRAY); 45 xx(CONST); 46 xx(VOLATILE); 47 #undef xx 48 case CONST+VOLATILE: 49 type = rcc_CONST(ty->size, ty->align, typeuid(ty->type)); 50 break; 51 case ENUM: { 52 list_ty ids = Seq_new(0); 53 int i; 54 for (i = 0; ty->u.sym->u.idlist[i] != NULL; i++) 55 Seq_addhi(ids, rcc_enum_(ty->u.sym->u.idlist[i]->name, 56 ty->u.sym->u.idlist[i]->u.value)); 57 assert(i > 0); 58 type = rcc_ENUM(ty->size, ty->align, ty->u.sym->name, ids); 59 break; 60 } 61 case STRUCT: case UNION: { 62 list_ty fields = Seq_new(0); 63 Field p = fieldlist(ty); 64 for ( ; p != NULL; p = p->link) 65 Seq_addhi(fields, rcc_field(p->name, typeuid(p->type), p->offset, p->bitsize, p->lsb)); 66 if (ty->op == STRUCT) 67 type = rcc_STRUCT(ty->size, ty->align, ty->u.sym->name, fields); 68 else 69 type = rcc_UNION (ty->size, ty->align, ty->u.sym->name, fields); 70 break; 71 } 72 case FUNCTION: { 73 list_ty formals = Seq_new(0); 74 if (ty->u.f.proto != NULL && ty->u.f.proto[0] != NULL) { 75 int i; 76 for (i = 0; ty->u.f.proto[i] != NULL; i++) 77 Seq_addhi(formals, to_generic_int(typeuid(ty->u.f.proto[i]))); 78 } else if (ty->u.f.proto != NULL && ty->u.f.proto[0] == NULL) 79 Seq_addhi(formals, to_generic_int(typeuid(voidtype))); 80 type = rcc_FUNCTION(ty->size, ty->align, typeuid(ty->type), formals); 81 break; 82 } 83 default: assert(0); 84 } 85 Seq_addhi(pickle->items, rcc_Type(ty->x.typeno, type)); 86 return ty->x.typeno; 87 } 88 89 static int symboluid(Symbol p) { 90 assert(p); 91 assert(p->scope != CONSTANTS && p->scope != LABELS); 92 if (p->x.offset == 0) 93 p->x.offset = pickle->nuids++; 94 return p->x.offset; 95 } 96 97 static rcc_symbol_ty mk_symbol(Symbol p) { 98 int flags = 0, ref = 10000*p->ref; 99 100 if (p->ref > 0 && ref == 0) 101 ref++; 102 #define xx(f,n) flags |= p->f<<n; 103 xx(structarg,0) 104 xx(addressed,1) 105 xx(computed,2) 106 xx(temporary,3) 107 xx(generated,4) 108 #undef xx 109 return rcc_symbol(p->name, typeuid(p->type), p->scope, p->sclass, ref, flags); 110 } 111 112 static rcc_real_ty mk_real(int size, Value v) { 113 unsigned *p = (unsigned *)&v.d; 114 return rcc_real(p[swap], p[1-swap]); 115 } 116 117 static void asdl_segment(int n) { 118 static int cseg; 119 120 if (cseg != n) 121 put(rcc_Segment(cseg = n)); 122 } 123 124 static void asdl_address(Symbol q, Symbol p, long n) { 125 assert(q->x.offset == 0); 126 put(rcc_Address(symboluid(q), mk_symbol(q), symboluid(p), n)); 127 } 128 129 static void asdl_blockbeg(Env *e) { 130 put(rcc_Blockbeg()); 131 } 132 133 static void asdl_blockend(Env *e) { 134 put(rcc_Blockend()); 135 } 136 137 static void asdl_defaddress(Symbol p) { 138 if (p->scope == LABELS) 139 put(rcc_Deflabel(p->u.l.label)); 140 else 141 put(rcc_Defaddress(symboluid(p))); 142 } 143 144 static void asdl_defconst(int suffix, int size, Value v) { 145 switch (suffix) { 146 case I: put(rcc_Defconst(suffix, size, v.i)); return; 147 case U: put(rcc_Defconst(suffix, size, v.u)); return; 148 case P: put(rcc_Defconst(suffix, size, (unsigned long)v.p)); return; /* FIXME */ 149 case F: put(rcc_Defconstf(size, mk_real(size, v))); return; 150 assert(0); 151 } 152 } 153 154 static void asdl_defstring(int len, char *str) { 155 put(rcc_Defstring(Text_box(stringn(str, len), len))); 156 } 157 158 static void asdl_defsymbol(Symbol p) { 159 if (p->scope >= GLOBAL) 160 symboluid(p); 161 } 162 163 static Symbol temps; 164 165 static rcc_node_ty visit(Node p) { 166 Symbol q; 167 rcc_node_ty left = NULL, right = NULL; 168 int suffix = optype(p->op), size = opsize(p->op); 169 170 assert(p); 171 for (q = temps; q; q = q->u.t.next) 172 if (q->u.t.cse == p) { 173 q->u.t.cse = NULL; 174 return rcc_CSE(0, 0, symboluid(q), visit(p)); 175 } 176 if (p->kids[0] != NULL) 177 left = visit(p->kids[0]); 178 if (p->kids[1] != NULL) 179 right = visit(p->kids[1]); 180 switch (specific(p->op)) { 181 case CNST+F: 182 assert(p->syms[0]); 183 return rcc_CNSTF(suffix, size, mk_real(size, p->syms[0]->u.c.v)); 184 case CALL+B: 185 assert(p->syms[0]); 186 assert(p->syms[0]->type); 187 return rcc_CALLB(suffix, size, left, right, typeuid(p->syms[0]->type)); 188 case RET+V: 189 return rcc_RET(suffix, size); 190 case LABEL+V: 191 assert(p->syms[0]); 192 return rcc_LABEL(suffix, size, p->syms[0]->u.l.label); 193 } 194 switch (generic(p->op)) { 195 case CNST: 196 assert(p->syms[0]); 197 return rcc_CNST(suffix, size, p->syms[0]->u.c.v.i); /* FIXME */ 198 case ARG: 199 assert(p->syms[0]); 200 return rcc_ARG(suffix, size, left, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i); 201 case ASGN: 202 assert(p->syms[0]); 203 assert(p->syms[1]); 204 return rcc_ASGN(suffix, size, left, right, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i); 205 case CVF: case CVI: case CVP: case CVU: 206 assert(p->syms[0]); 207 return rcc_CVT(suffix, size, generic(p->op), left, p->syms[0]->u.c.v.i); 208 case CALL: 209 assert(p->syms[0]); 210 assert(p->syms[0]->type); 211 return rcc_CALL(suffix, size, left, typeuid(p->syms[0]->type)); 212 #define xx(op) case op: return rcc_##op(suffix, size, symboluid(p->syms[0])) 213 xx(ADDRG); 214 xx(ADDRF); 215 #undef xx 216 case ADDRL: 217 if (!p->syms[0]->defined) 218 (*IR->local)(p->syms[0]); 219 p->syms[0]->defined = 1; 220 return rcc_ADDRL(suffix, size, symboluid(p->syms[0])); 221 case JUMP: 222 if (p->syms[0] != NULL) 223 return rcc_BRANCH(suffix, size, p->syms[0]->u.l.label); 224 return rcc_Unary(suffix, size, generic(p->op), left); 225 case INDIR: case RET: case NEG: case BCOM: 226 return rcc_Unary(suffix, size, generic(p->op), left); 227 case BOR: case BAND: case BXOR: case RSH: case LSH: 228 case ADD: case SUB: case DIV: case MUL: case MOD: 229 return rcc_Binary(suffix, size, generic(p->op), left, right); 230 case EQ: case NE: case GT: case GE: case LE: case LT: 231 assert(p->syms[0]); 232 return rcc_Compare(suffix, size, generic(p->op), left, right, p->syms[0]->u.l.label); 233 } 234 assert(0); 235 return NULL; 236 } 237 238 static void asdl_emit(Node p) {} 239 240 static void asdl_local(Symbol p) { 241 assert(p->x.offset == 0); 242 put(rcc_Local(symboluid(p), mk_symbol(p))); 243 if (p->temporary && p->u.t.cse) { 244 p->u.t.next = temps; 245 temps = p; 246 } 247 } 248 249 static Symbol pending = NULL; 250 251 static void dopending(Symbol p) { 252 if (pending != NULL) { 253 int uid = symboluid(pending); 254 rcc_symbol_ty symbol = mk_symbol(pending); 255 Seq_addhi(pickle->items, rcc_Symbol(uid, symbol)); 256 } 257 pending = p; 258 } 259 260 261 static void asdl_export(Symbol p) { 262 put(rcc_Export(symboluid(p))); 263 } 264 265 static void asdl_function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { 266 list_ty codelist = Seq_new(0), save, calleelist = Seq_new(0), callerlist = Seq_new(0); 267 int i; 268 269 dopending(f); 270 for (i = 0; caller[i] != NULL; i++) { 271 asdl_local(caller[i]); 272 Seq_addhi(callerlist, to_generic_int(symboluid(caller[i]))); 273 } 274 for (i = 0; callee[i] != NULL; i++) { 275 asdl_local(callee[i]); 276 Seq_addhi(calleelist, to_generic_int(symboluid(callee[i]))); 277 } 278 save = interfaces; 279 interfaces = codelist; 280 gencode(caller, callee); 281 asdl_segment(CODE); 282 emitcode(); 283 interfaces = save; 284 put(rcc_Function(symboluid(f), callerlist, calleelist, ncalls, codelist)); 285 } 286 287 static Node asdl_gen(Node p) { 288 Node q; 289 list_ty forest = Seq_new(0); 290 291 for (q = p; p != NULL; p = p->link) 292 if (specific(p->op) == JUMP+V && specific(p->kids[0]->op) == ADDRG+P 293 && p->kids[0]->syms[0]->scope == LABELS) { 294 p->syms[0] = p->kids[0]->syms[0]; 295 p->kids[0] = NULL; 296 } 297 for (p = q; p != NULL; p = p->link) 298 Seq_addhi(forest, visit(p)); 299 put(rcc_Forest(forest)); 300 temps = NULL; 301 return q; 302 } 303 304 static void asdl_global(Symbol p) { 305 dopending(p); 306 put(rcc_Global(symboluid(p), p->u.seg)); 307 } 308 309 static void asdl_import(Symbol p) { 310 dopending(p); 311 put(rcc_Import(symboluid(p))); 312 } 313 314 static void asdl_progbeg(int argc, char *argv[]) { 315 int i; 316 317 #if WIN32 318 _setmode(_fileno(stdout), _O_BINARY); 319 #endif 320 pickle = rcc_program(1, 0, Seq_new(0), Seq_new(0), argc, Seq_new(0)); 321 for (i = 0; i < argc; i++) 322 Seq_addhi(pickle->argv, to_generic_string(Text_box(argv[i], strlen(argv[i]) + 1))); 323 interfaces = pickle->interfaces; 324 } 325 326 static int checkuid(list_ty list) { 327 int i, n = 0, count = Seq_length(list); 328 329 for (i = 0; i < count; i++) { 330 rcc_interface_ty in = Seq_get(list, i); 331 if (in->kind == rcc_Local_enum 332 || in->kind == rcc_Address_enum) 333 n++; 334 else if (in->kind == rcc_Function_enum) 335 n += checkuid(in->v.rcc_Function.codelist); 336 } 337 return n; 338 } 339 340 static void asdl_progend(void) { 341 dopending(NULL); 342 { 343 int n = checkuid(pickle->interfaces) + Seq_length(pickle->items); 344 if (n != pickle->nuids - 1) 345 fprintf(stderr, "?bogus uid count: have %d should have %d\n", 346 n, pickle->nuids-1); 347 } 348 pickle->nlabels = genlabel(0); 349 write_int((int)(100*(assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL)) 350 ), stdout); 351 rcc_write_program(pickle, stdout); 352 } 353 static void asdl_space(int n) { 354 put(rcc_Space(n)); 355 } 356 357 void asdl_init(int argc, char *argv[]) { 358 int i; 359 static int inited; 360 361 if (inited) 362 return; 363 inited = 1; 364 for (i = 1; i < argc; i++) 365 if (strcmp(argv[i], "-asdl") == 0) { 366 #define xx(f) IR->f = asdl_##f 367 xx(address); 368 xx(blockbeg); 369 xx(blockend); 370 xx(defaddress); 371 xx(defconst); 372 xx(defstring); 373 xx(defsymbol); 374 xx(emit); 375 xx(export); 376 xx(function); 377 xx(gen); 378 xx(global); 379 xx(import); 380 xx(local); 381 xx(progbeg); 382 xx(progend); 383 xx(segment); 384 xx(space); 385 #undef xx 386 #define xx(f) IR->f = 0 387 xx(stabblock); 388 xx(stabend); 389 xx(stabfend); 390 xx(stabinit); 391 xx(stabline); 392 xx(stabsym); 393 xx(stabtype); 394 #undef xx 395 IR->wants_dag = 0; 396 prunetemps = 0; /* pass2 prunes useless temps */ 397 assignargs = 0; /* pass2 generates caller to callee assignments */ 398 } 399 }