1 2NAMELEN: con 28; 3 4cache: array of byte; 5ncached: int; 6ndatum: int; 7startoff: int; 8lastoff: int; 9lastkind: int; 10 11discon(val: int) 12{ 13 if(val >= -64 && val <= 63){ 14 bout.putb(byte (val & ~16r80)); 15 return; 16 } 17 if(val >= -8192 && val <= 8191){ 18 bout.putb(byte ((val>>8) & ~16rC0 | 16r80)); 19 bout.putb(byte val); 20 return; 21 } 22 if(val < 0 && ((val >> 29) & 7) != 7 23 || val > 0 && (val >> 29) != 0) 24 fatal("overflow in constant 16r"+hex(val, 0)); 25 bout.putb(byte(val>>24 | 16rC0)); 26 bout.putb(byte(val>>16)); 27 bout.putb(byte(val>>8)); 28 bout.putb(byte val); 29} 30 31disword(w: int) 32{ 33 bout.putb(byte(w >> 24)); 34 bout.putb(byte(w >> 16)); 35 bout.putb(byte(w >> 8)); 36 bout.putb(byte w); 37} 38 39disdata(kind, n: int) 40{ 41 if(n < DMAX && n != 0) 42 bout.putb(byte((kind << DBYTE) | n)); 43 else{ 44 bout.putb(byte kind << DBYTE); 45 discon(n); 46 } 47} 48 49dismod(m: ref Decl) 50{ 51 fileoff := bout.seek(big 0, 1); 52 name := array of byte m.sym.name; 53 n := len name; 54 if(n > NAMELEN-1) 55 n = NAMELEN-1; 56 bout.write(name, n); 57 bout.putb(byte 0); 58 for(m = m.ty.tof.ids; m != nil; m = m.next){ 59 case m.store{ 60 Dglobal => 61 discon(-1); 62 discon(-1); 63 disword(sign(m)); 64 bout.puts(".mp"); 65 bout.putb(byte 0); 66 Dfn => 67 discon(m.pc.pc); 68 discon(m.desc.id); 69 disword(sign(m)); 70 if(m.dot.ty.kind == Tadt){ 71 bout.puts(m.dot.sym.name); 72 bout.putb(byte '.'); 73 } 74 bout.puts(m.sym.name); 75 bout.putb(byte 0); 76 * => 77 fatal("unknown kind in dismod: "+declconv(m)); 78 } 79 } 80 if(debug['s']) 81 print("%bd linkage bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff); 82} 83 84dispath() 85{ 86 sp := array of byte srcpath(); 87 bout.write(sp, len sp); 88 bout.putb(byte 0); 89} 90 91disentry(e: ref Decl) 92{ 93 if(e == nil){ 94 discon(-1); 95 discon(-1); 96 return; 97 } 98 discon(e.pc.pc); 99 discon(e.desc.id); 100} 101 102disdesc(d: ref Desc) 103{ 104 fileoff := bout.seek(big 0, 1); 105 for(; d != nil; d = d.next){ 106 discon(d.id); 107 discon(d.size); 108 discon(d.nmap); 109 bout.write(d.map, d.nmap); 110 } 111 if(debug['s']) 112 print("%bd type descriptor bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff); 113} 114 115disvar(nil: int, ids: ref Decl) 116{ 117 fileoff := bout.seek(big 0, 1); 118 lastkind = -1; 119 ncached = 0; 120 ndatum = 0; 121 122 for(d := ids; d != nil; d = d.next) 123 if(d.store == Dglobal && d.init != nil) 124 disdatum(d.offset, d.init); 125 126 disflush(-1, -1, 0); 127 128 bout.putb(byte 0); 129 130 if(debug['s']) 131 print("%bd data bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff); 132} 133 134disldt(size: int, ds: ref Decl) 135{ 136 if(0){ 137 discon(size); 138 disvar(size, ds); 139 return; 140 } 141 142 m := 0; 143 for(d := ds; d != nil; d = d.next) 144 if(d.store == Dglobal && d.init != nil) 145 m++; 146 discon(m); 147 n: ref Node; 148 for(d = ds; d != nil; d = d.next){ 149 if(d.store == Dglobal && d.init != nil){ 150 n = d.init; 151 if(n.ty.kind != Tiface) 152 nerror(n, "disldt: not Tiface"); 153 discon(int n.c.val); 154 for(id := n.decl.ty.ids; id != nil; id = id.next){ 155 disword(sign(id)); 156 if(id.dot.ty.kind == Tadt){ 157 s := array of byte id.dot.sym.name; 158 bout.write(s, len s); 159 bout.putb(byte '.'); 160 } 161 s := array of byte id.sym.name; 162 bout.write(s, len s); 163 bout.putb(byte 0); 164 } 165 } 166 } 167 discon(0); 168} 169 170disdatum(offset: int, n: ref Node) 171{ 172 c: ref Case; 173 lab: Label; 174 id: ref Decl; 175 wild: ref Node; 176 i, e: int; 177 178 case n.ty.kind{ 179 Tbyte => 180 disbyte(offset, byte n.c.val); 181 Tint or 182 Tfix => 183 disint(offset, int n.c.val); 184 Tbig => 185 disbig(offset, n.c.val); 186 Tstring => 187 disstring(offset, n.decl.sym); 188 Treal => 189 disreal(offset, n.c.rval); 190 Tadt or 191 Tadtpick or 192 Ttuple => 193 id = n.ty.ids; 194 for(n = n.left; n != nil; n = n.right){ 195 disdatum(offset + id.offset, n.left); 196 id = id.next; 197 } 198 Tany => 199 break; 200 Tcase => 201 c = n.ty.cse; 202 disint(offset, c.nlab); 203 offset += IBY2WD; 204 for(i = 0; i < c.nlab; i++){ 205 lab = c.labs[i]; 206 disint(offset, int lab.start.c.val); 207 offset += IBY2WD; 208 disint(offset, int lab.stop.c.val+1); 209 offset += IBY2WD; 210 disint(offset, lab.inst.pc); 211 offset += IBY2WD; 212 } 213 if(c.iwild != nil) 214 disint(offset, c.iwild.pc); 215 else 216 disint(offset, -1); 217 Tcasel => 218 c = n.ty.cse; 219 disint(offset, c.nlab); 220 offset += 2*IBY2WD; 221 for(i = 0; i < c.nlab; i++){ 222 lab = c.labs[i]; 223 disbig(offset, lab.start.c.val); 224 offset += IBY2LG; 225 disbig(offset, lab.stop.c.val+big 1); 226 offset += IBY2LG; 227 disint(offset, lab.inst.pc); 228 offset += 2*IBY2WD; 229 } 230 if(c.iwild != nil) 231 disint(offset, c.iwild.pc); 232 else 233 disint(offset, -1); 234 Tcasec => 235 c = n.ty.cse; 236 disint(offset, c.nlab); 237 offset += IBY2WD; 238 for(i = 0; i < c.nlab; i++){ 239 lab = c.labs[i]; 240 disstring(offset, lab.start.decl.sym); 241 offset += IBY2WD; 242 if(lab.stop != lab.start) 243 disstring(offset, lab.stop.decl.sym); 244 offset += IBY2WD; 245 disint(offset, lab.inst.pc); 246 offset += IBY2WD; 247 } 248 if(c.iwild != nil) 249 disint(offset, c.iwild.pc); 250 else 251 disint(offset, -1); 252 Tgoto => 253 c = n.ty.cse; 254 disint(offset, n.ty.size/IBY2WD-1); 255 offset += IBY2WD; 256 for(i = 0; i < c.nlab; i++){ 257 disint(offset, c.labs[i].inst.pc); 258 offset += IBY2WD; 259 } 260 if(c.iwild != nil) 261 disint(offset, c.iwild.pc); 262 Tarray => 263 disflush(-1, -1, 0); 264 disdata(DEFA, 1); # 1 is ignored 265 discon(offset); 266 disword(n.ty.tof.decl.desc.id); 267 disword(int n.left.c.val); 268 269 if(n.right == nil) 270 break; 271 272 disdata(DIND, 1); # 1 is ignored 273 discon(offset); 274 disword(0); 275 276 c = n.right.ty.cse; 277 wild = nil; 278 if(c.wild != nil) 279 wild = c.wild.right; 280 last := 0; 281 esz := n.ty.tof.size; 282 for(i = 0; i < c.nlab; i++){ 283 e = int c.labs[i].start.c.val; 284 if(wild != nil){ 285 for(; last < e; last++) 286 disdatum(esz * last, wild); 287 } 288 last = e; 289 e = int c.labs[i].stop.c.val; 290 elem := c.labs[i].node.right; 291 for(; last <= e; last++) 292 disdatum(esz * last, elem); 293 } 294 if(wild != nil) 295 for(e = int n.left.c.val; last < e; last++) 296 disdatum(esz * last, wild); 297 298 disflush(-1, -1, 0); 299 disdata(DAPOP, 1); # 1 is ignored 300 discon(0); 301 Tiface => 302 disint(offset, int n.c.val); 303 offset += IBY2WD; 304 for(id = n.decl.ty.ids; id != nil; id = id.next){ 305 offset = align(offset, IBY2WD); 306 disint(offset, sign(id)); 307 offset += IBY2WD; 308 309 name: array of byte; 310 if(id.dot.ty.kind == Tadt){ 311 name = array of byte id.dot.sym.name; 312 disbytes(offset, name); 313 offset += len name; 314 disbyte(offset, byte '.'); 315 offset++; 316 } 317 name = array of byte id.sym.name; 318 disbytes(offset, name); 319 offset += len name; 320 disbyte(offset, byte 0); 321 offset++; 322 } 323 * => 324 fatal("can't gen global "+nodeconv(n)); 325 } 326} 327 328disexc(es: ref Except) 329{ 330 e: ref Except; 331 332 n := 0; 333 for(e = es; e != nil; e = e.next) 334 if(int e.p1.reach || int e.p2.reach) 335 n++; 336 discon(n); 337 for(e = es; e != nil; e = e.next){ 338 if(!int e.p1.reach && !int e.p2.reach) 339 continue; 340 c := e.c; 341 discon(e.d.offset); 342 discon(getpc(e.p1)); 343 discon(getpc(e.p2)); 344 if(e.desc != nil) 345 discon(e.desc.id); 346 else 347 discon(-1); 348 discon(c.nlab|(e.ne<<16)); 349 for(i := 0; i < c.nlab; i++){ 350 lab := c.labs[i]; 351 d := lab.start.decl; 352 if(lab.start.ty.kind == Texception) 353 d = d.init.decl; 354 bout.puts(d.sym.name); 355 bout.putb(byte 0); 356 discon(lab.inst.pc); 357 } 358 if(c.iwild == nil) 359 discon(-1); 360 else 361 discon(c.iwild.pc); 362 } 363 discon(0); 364} 365 366disbyte(off: int, v: byte) 367{ 368 disflush(DEFB, off, 1); 369 cache[ncached++] = v; 370 ndatum++; 371} 372 373disbytes(off: int, v: array of byte) 374{ 375 n := len v; 376 disflush(DEFB, off, n); 377 cache[ncached:] = v; 378 ncached += n; 379 ndatum += n; 380} 381 382disint(off, v: int) 383{ 384 disflush(DEFW, off, IBY2WD); 385 cache[ncached++] = byte(v >> 24); 386 cache[ncached++] = byte(v >> 16); 387 cache[ncached++] = byte(v >> 8); 388 cache[ncached++] = byte(v); 389 ndatum++; 390} 391 392disbig(off: int, v: big) 393{ 394 disflush(DEFL, off, IBY2LG); 395 iv := int(v >> 32); 396 cache[ncached++] = byte(iv >> 24); 397 cache[ncached++] = byte(iv >> 16); 398 cache[ncached++] = byte(iv >> 8); 399 cache[ncached++] = byte(iv); 400 iv = int v; 401 cache[ncached++] = byte(iv >> 24); 402 cache[ncached++] = byte(iv >> 16); 403 cache[ncached++] = byte(iv >> 8); 404 cache[ncached++] = byte(iv); 405 ndatum++; 406} 407 408disreal(off: int, v: real) 409{ 410 disflush(DEFF, off, IBY2LG); 411 export_real(cache[ncached:ncached+8], array[] of {v}); 412 ncached += IBY2LG; 413 ndatum++; 414} 415 416disstring(offset: int, sym: ref Sym) 417{ 418 disflush(-1, -1, 0); 419 d := array of byte sym.name; 420 disdata(DEFS, len d); 421 discon(offset); 422 bout.write(d, len d); 423} 424 425disflush(kind, off, size: int) 426{ 427 if(kind != lastkind || off != lastoff){ 428 if(lastkind != -1 && ncached){ 429 disdata(lastkind, ndatum); 430 discon(startoff); 431 bout.write(cache, ncached); 432 } 433 startoff = off; 434 lastkind = kind; 435 ncached = 0; 436 ndatum = 0; 437 } 438 lastoff = off + size; 439 while(kind >= 0 && ncached + size >= len cache){ 440 c := array[ncached + 1024] of byte; 441 c[0:] = cache; 442 cache = c; 443 } 444} 445 446dismode := array[int Aend] of 447{ 448 int Aimm => byte AIMM, 449 int Amp => byte AMP, 450 int Ampind => byte(AMP|AIND), 451 int Afp => byte AFP, 452 int Afpind => byte(AFP|AIND), 453 int Apc => byte AIMM, 454 int Adesc => byte AIMM, 455 int Aoff => byte AIMM, 456 int Anoff => byte AIMM, 457 int Aerr => byte AXXX, 458 int Anone => byte AXXX, 459 int Aldt => byte AIMM, 460}; 461 462disregmode := array[int Aend] of 463{ 464 int Aimm => byte AXIMM, 465 int Amp => byte AXINM, 466 int Ampind => byte AXNON, 467 int Afp => byte AXINF, 468 int Afpind => byte AXNON, 469 int Apc => byte AXIMM, 470 int Adesc => byte AXIMM, 471 int Aoff => byte AXIMM, 472 int Anoff => byte AXIMM, 473 int Aerr => byte AXNON, 474 int Anone => byte AXNON, 475 int Aldt => byte AXIMM, 476}; 477 478MAXCON: con 4; 479MAXADDR: con 2*MAXCON; 480MAXINST: con 3*MAXADDR+2; 481NIBUF: con 1024; 482 483ibuf: array of byte; 484nibuf: int; 485 486disinst(in: ref Inst) 487{ 488 fileoff := bout.seek(big 0, 1); 489 ibuf = array[NIBUF] of byte; 490 nibuf = 0; 491 for(; in != nil; in = in.next){ 492 if(in.op == INOOP) 493 continue; 494 if(nibuf >= NIBUF-MAXINST){ 495 bout.write(ibuf, nibuf); 496 nibuf = 0; 497 } 498 ibuf[nibuf++] = byte in.op; 499 o := dismode[int in.sm] << SRC; 500 o |= dismode[int in.dm] << DST; 501 o |= disregmode[int in.mm]; 502 ibuf[nibuf++] = o; 503 if(in.mm != Anone) 504 disaddr(in.mm, in.m); 505 if(in.sm != Anone) 506 disaddr(in.sm, in.s); 507 if(in.dm != Anone) 508 disaddr(in.dm, in.d); 509 } 510 if(nibuf > 0) 511 bout.write(ibuf, nibuf); 512 ibuf = nil; 513 514 if(debug['s']) 515 print("%bd instruction bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff); 516} 517 518disaddr(m: byte, a: Addr) 519{ 520 val := 0; 521 case int m{ 522 int Aimm or 523 int Apc or 524 int Adesc => 525 val = a.offset; 526 int Aoff => 527 val = a.decl.iface.offset; 528 int Anoff => 529 val = -(a.decl.iface.offset+1); 530 int Afp or 531 int Amp or 532 int Aldt => 533 val = a.reg; 534 int Afpind or 535 int Ampind => 536 disbcon(a.reg); 537 val = a.offset; 538 } 539 disbcon(val); 540} 541 542disbcon(val: int) 543{ 544 if(val >= -64 && val <= 63){ 545 ibuf[nibuf++] = byte(val & ~16r80); 546 return; 547 } 548 if(val >= -8192 && val <= 8191){ 549 ibuf[nibuf++] = byte(val>>8 & ~16rC0 | 16r80); 550 ibuf[nibuf++] = byte val; 551 return; 552 } 553 if(val < 0 && ((val >> 29) & 7) != 7 554 || val > 0 && (val >> 29) != 0) 555 fatal("overflow in constant 16r"+hex(val, 0)); 556 ibuf[nibuf++] = byte(val>>24 | 16rC0); 557 ibuf[nibuf++] = byte(val>>16); 558 ibuf[nibuf++] = byte(val>>8); 559 ibuf[nibuf++] = byte val; 560} 561