github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/6a/a.y (about) 1 // Inferno utils/6a/a.y 2 // http://code.google.com/p/inferno-os/source/browse/utils/6a/a.y 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 %{ 32 #include <u.h> 33 #include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */ 34 #include <libc.h> 35 #include "a.h" 36 #include "../../runtime/funcdata.h" 37 %} 38 %union { 39 Sym *sym; 40 vlong lval; 41 double dval; 42 char sval[8]; 43 Addr addr; 44 Addr2 addr2; 45 } 46 %left '|' 47 %left '^' 48 %left '&' 49 %left '<' '>' 50 %left '+' '-' 51 %left '*' '/' '%' 52 %token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 53 %token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG LTYPEPC 54 %token <lval> LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT LTYPEF 55 %token <lval> LCONST LFP LPC LSB 56 %token <lval> LBREG LLREG LSREG LFREG LMREG LXREG 57 %token <dval> LFCONST 58 %token <sval> LSCONST LSP 59 %token <sym> LNAME LLAB LVAR 60 %type <lval> con con2 expr pointer offset 61 %type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem 62 %type <addr2> nonnon nonrel nonrem rimnon rimrem remrim 63 %type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 64 %type <addr2> spec10 spec11 spec12 spec13 65 %% 66 prog: 67 | prog 68 { 69 stmtline = lineno; 70 } 71 line 72 73 line: 74 LNAME ':' 75 { 76 $1 = labellookup($1); 77 if($1->type == LLAB && $1->value != pc) 78 yyerror("redeclaration of %s (%s)", $1->labelname, $1->name); 79 $1->type = LLAB; 80 $1->value = pc; 81 } 82 line 83 | ';' 84 | inst ';' 85 | error ';' 86 87 inst: 88 LNAME '=' expr 89 { 90 $1->type = LVAR; 91 $1->value = $3; 92 } 93 | LVAR '=' expr 94 { 95 if($1->value != $3) 96 yyerror("redeclaration of %s", $1->name); 97 $1->value = $3; 98 } 99 | LTYPE0 nonnon { outcode($1, &$2); } 100 | LTYPE1 nonrem { outcode($1, &$2); } 101 | LTYPE2 rimnon { outcode($1, &$2); } 102 | LTYPE3 rimrem { outcode($1, &$2); } 103 | LTYPE4 remrim { outcode($1, &$2); } 104 | LTYPER nonrel { outcode($1, &$2); } 105 | LTYPED spec1 { outcode($1, &$2); } 106 | LTYPET spec2 { outcode($1, &$2); } 107 | LTYPEC spec3 { outcode($1, &$2); } 108 | LTYPEN spec4 { outcode($1, &$2); } 109 | LTYPES spec5 { outcode($1, &$2); } 110 | LTYPEM spec6 { outcode($1, &$2); } 111 | LTYPEI spec7 { outcode($1, &$2); } 112 | LTYPEXC spec8 { outcode($1, &$2); } 113 | LTYPEX spec9 { outcode($1, &$2); } 114 | LTYPERT spec10 { outcode($1, &$2); } 115 | LTYPEG spec11 { outcode($1, &$2); } 116 | LTYPEPC spec12 { outcode($1, &$2); } 117 | LTYPEF spec13 { outcode($1, &$2); } 118 119 nonnon: 120 { 121 $$.from = nullgen; 122 $$.to = nullgen; 123 } 124 | ',' 125 { 126 $$.from = nullgen; 127 $$.to = nullgen; 128 } 129 130 rimrem: 131 rim ',' rem 132 { 133 $$.from = $1; 134 $$.to = $3; 135 } 136 137 remrim: 138 rem ',' rim 139 { 140 $$.from = $1; 141 $$.to = $3; 142 } 143 144 rimnon: 145 rim ',' 146 { 147 $$.from = $1; 148 $$.to = nullgen; 149 } 150 | rim 151 { 152 $$.from = $1; 153 $$.to = nullgen; 154 } 155 156 nonrem: 157 ',' rem 158 { 159 $$.from = nullgen; 160 $$.to = $2; 161 } 162 | rem 163 { 164 $$.from = nullgen; 165 $$.to = $1; 166 } 167 168 nonrel: 169 ',' rel 170 { 171 $$.from = nullgen; 172 $$.to = $2; 173 } 174 | rel 175 { 176 $$.from = nullgen; 177 $$.to = $1; 178 } 179 | imm ',' rel 180 { 181 $$.from = $1; 182 $$.to = $3; 183 } 184 185 spec1: /* DATA */ 186 nam '/' con ',' imm 187 { 188 $$.from = $1; 189 $$.from.scale = $3; 190 $$.to = $5; 191 } 192 193 spec2: /* TEXT */ 194 mem ',' imm2 195 { 196 settext($1.sym); 197 $$.from = $1; 198 $$.to = $3; 199 } 200 | mem ',' con ',' imm2 201 { 202 settext($1.sym); 203 $$.from = $1; 204 $$.from.scale = $3; 205 $$.to = $5; 206 } 207 208 spec3: /* JMP/CALL */ 209 ',' rom 210 { 211 $$.from = nullgen; 212 $$.to = $2; 213 } 214 | rom 215 { 216 $$.from = nullgen; 217 $$.to = $1; 218 } 219 220 spec4: /* NOP */ 221 nonnon 222 | nonrem 223 224 spec5: /* SHL/SHR */ 225 rim ',' rem 226 { 227 $$.from = $1; 228 $$.to = $3; 229 } 230 | rim ',' rem ':' LLREG 231 { 232 $$.from = $1; 233 $$.to = $3; 234 if($$.from.index != D_NONE) 235 yyerror("dp shift with lhs index"); 236 $$.from.index = $5; 237 } 238 239 spec6: /* MOVW/MOVL */ 240 rim ',' rem 241 { 242 $$.from = $1; 243 $$.to = $3; 244 } 245 | rim ',' rem ':' LSREG 246 { 247 $$.from = $1; 248 $$.to = $3; 249 if($$.to.index != D_NONE) 250 yyerror("dp move with lhs index"); 251 $$.to.index = $5; 252 } 253 254 spec7: 255 rim ',' 256 { 257 $$.from = $1; 258 $$.to = nullgen; 259 } 260 | rim 261 { 262 $$.from = $1; 263 $$.to = nullgen; 264 } 265 | rim ',' rem 266 { 267 $$.from = $1; 268 $$.to = $3; 269 } 270 271 spec8: /* CMPPS/CMPPD */ 272 reg ',' rem ',' con 273 { 274 $$.from = $1; 275 $$.to = $3; 276 $$.to.offset = $5; 277 } 278 279 spec9: /* shufl */ 280 imm ',' rem ',' reg 281 { 282 $$.from = $3; 283 $$.to = $5; 284 if($1.type != D_CONST) 285 yyerror("illegal constant"); 286 $$.to.offset = $1.offset; 287 } 288 289 spec10: /* RET/RETF */ 290 { 291 $$.from = nullgen; 292 $$.to = nullgen; 293 } 294 | imm 295 { 296 $$.from = $1; 297 $$.to = nullgen; 298 } 299 300 spec11: /* GLOBL */ 301 mem ',' imm 302 { 303 $$.from = $1; 304 $$.to = $3; 305 } 306 | mem ',' con ',' imm 307 { 308 $$.from = $1; 309 $$.from.scale = $3; 310 $$.to = $5; 311 } 312 313 spec12: /* PCDATA */ 314 rim ',' rim 315 { 316 if($1.type != D_CONST || $3.type != D_CONST) 317 yyerror("arguments to PCDATA must be integer constants"); 318 $$.from = $1; 319 $$.to = $3; 320 } 321 322 spec13: /* FUNCDATA */ 323 rim ',' rim 324 { 325 if($1.type != D_CONST) 326 yyerror("index for FUNCDATA must be integer constant"); 327 if($3.type != D_EXTERN && $3.type != D_STATIC) 328 yyerror("value for FUNCDATA must be symbol reference"); 329 $$.from = $1; 330 $$.to = $3; 331 } 332 333 rem: 334 reg 335 | mem 336 337 rom: 338 rel 339 | nmem 340 | '*' reg 341 { 342 $$ = $2; 343 } 344 | '*' omem 345 { 346 $$ = $2; 347 } 348 | reg 349 | omem 350 351 rim: 352 rem 353 | imm 354 355 rel: 356 con '(' LPC ')' 357 { 358 $$ = nullgen; 359 $$.type = D_BRANCH; 360 $$.offset = $1 + pc; 361 } 362 | LNAME offset 363 { 364 $1 = labellookup($1); 365 $$ = nullgen; 366 if(pass == 2 && $1->type != LLAB) 367 yyerror("undefined label: %s", $1->labelname); 368 $$.type = D_BRANCH; 369 $$.offset = $1->value + $2; 370 } 371 372 reg: 373 LBREG 374 { 375 $$ = nullgen; 376 $$.type = $1; 377 } 378 | LFREG 379 { 380 $$ = nullgen; 381 $$.type = $1; 382 } 383 | LLREG 384 { 385 $$ = nullgen; 386 $$.type = $1; 387 } 388 | LMREG 389 { 390 $$ = nullgen; 391 $$.type = $1; 392 } 393 | LSP 394 { 395 $$ = nullgen; 396 $$.type = D_SP; 397 } 398 | LSREG 399 { 400 $$ = nullgen; 401 $$.type = $1; 402 } 403 | LXREG 404 { 405 $$ = nullgen; 406 $$.type = $1; 407 } 408 imm2: 409 '$' con2 410 { 411 $$ = nullgen; 412 $$.type = D_CONST; 413 $$.offset = $2; 414 } 415 416 imm: 417 '$' con 418 { 419 $$ = nullgen; 420 $$.type = D_CONST; 421 $$.offset = $2; 422 } 423 | '$' nam 424 { 425 $$ = $2; 426 $$.index = $2.type; 427 $$.type = D_ADDR; 428 /* 429 if($2.type == D_AUTO || $2.type == D_PARAM) 430 yyerror("constant cannot be automatic: %s", 431 $2.sym->name); 432 */ 433 } 434 | '$' LSCONST 435 { 436 $$ = nullgen; 437 $$.type = D_SCONST; 438 memcpy($$.u.sval, $2, sizeof($$.u.sval)); 439 } 440 | '$' LFCONST 441 { 442 $$ = nullgen; 443 $$.type = D_FCONST; 444 $$.u.dval = $2; 445 } 446 | '$' '(' LFCONST ')' 447 { 448 $$ = nullgen; 449 $$.type = D_FCONST; 450 $$.u.dval = $3; 451 } 452 | '$' '(' '-' LFCONST ')' 453 { 454 $$ = nullgen; 455 $$.type = D_FCONST; 456 $$.u.dval = -$4; 457 } 458 | '$' '-' LFCONST 459 { 460 $$ = nullgen; 461 $$.type = D_FCONST; 462 $$.u.dval = -$3; 463 } 464 465 mem: 466 omem 467 | nmem 468 469 omem: 470 con 471 { 472 $$ = nullgen; 473 $$.type = D_INDIR+D_NONE; 474 $$.offset = $1; 475 } 476 | con '(' LLREG ')' 477 { 478 $$ = nullgen; 479 $$.type = D_INDIR+$3; 480 $$.offset = $1; 481 } 482 | con '(' LSP ')' 483 { 484 $$ = nullgen; 485 $$.type = D_INDIR+D_SP; 486 $$.offset = $1; 487 } 488 | con '(' LSREG ')' 489 { 490 $$ = nullgen; 491 $$.type = D_INDIR+$3; 492 $$.offset = $1; 493 } 494 | con '(' LLREG '*' con ')' 495 { 496 $$ = nullgen; 497 $$.type = D_INDIR+D_NONE; 498 $$.offset = $1; 499 $$.index = $3; 500 $$.scale = $5; 501 checkscale($$.scale); 502 } 503 | con '(' LLREG ')' '(' LLREG '*' con ')' 504 { 505 $$ = nullgen; 506 $$.type = D_INDIR+$3; 507 $$.offset = $1; 508 $$.index = $6; 509 $$.scale = $8; 510 checkscale($$.scale); 511 } 512 | con '(' LLREG ')' '(' LSREG '*' con ')' 513 { 514 $$ = nullgen; 515 $$.type = D_INDIR+$3; 516 $$.offset = $1; 517 $$.index = $6; 518 $$.scale = $8; 519 checkscale($$.scale); 520 } 521 | '(' LLREG ')' 522 { 523 $$ = nullgen; 524 $$.type = D_INDIR+$2; 525 } 526 | '(' LSP ')' 527 { 528 $$ = nullgen; 529 $$.type = D_INDIR+D_SP; 530 } 531 | '(' LLREG '*' con ')' 532 { 533 $$ = nullgen; 534 $$.type = D_INDIR+D_NONE; 535 $$.index = $2; 536 $$.scale = $4; 537 checkscale($$.scale); 538 } 539 | '(' LLREG ')' '(' LLREG '*' con ')' 540 { 541 $$ = nullgen; 542 $$.type = D_INDIR+$2; 543 $$.index = $5; 544 $$.scale = $7; 545 checkscale($$.scale); 546 } 547 548 nmem: 549 nam 550 { 551 $$ = $1; 552 } 553 | nam '(' LLREG '*' con ')' 554 { 555 $$ = $1; 556 $$.index = $3; 557 $$.scale = $5; 558 checkscale($$.scale); 559 } 560 561 nam: 562 LNAME offset '(' pointer ')' 563 { 564 $$ = nullgen; 565 $$.type = $4; 566 $$.sym = linklookup(ctxt, $1->name, 0); 567 $$.offset = $2; 568 } 569 | LNAME '<' '>' offset '(' LSB ')' 570 { 571 $$ = nullgen; 572 $$.type = D_STATIC; 573 $$.sym = linklookup(ctxt, $1->name, 1); 574 $$.offset = $4; 575 } 576 577 offset: 578 { 579 $$ = 0; 580 } 581 | '+' con 582 { 583 $$ = $2; 584 } 585 | '-' con 586 { 587 $$ = -$2; 588 } 589 590 pointer: 591 LSB 592 | LSP 593 { 594 $$ = D_AUTO; 595 } 596 | LFP 597 598 con: 599 LCONST 600 | LVAR 601 { 602 $$ = $1->value; 603 } 604 | '-' con 605 { 606 $$ = -$2; 607 } 608 | '+' con 609 { 610 $$ = $2; 611 } 612 | '~' con 613 { 614 $$ = ~$2; 615 } 616 | '(' expr ')' 617 { 618 $$ = $2; 619 } 620 621 con2: 622 LCONST 623 { 624 $$ = ($1 & 0xffffffffLL) + 625 ((vlong)ArgsSizeUnknown << 32); 626 } 627 | '-' LCONST 628 { 629 $$ = (-$2 & 0xffffffffLL) + 630 ((vlong)ArgsSizeUnknown << 32); 631 } 632 | LCONST '-' LCONST 633 { 634 $$ = ($1 & 0xffffffffLL) + 635 (($3 & 0xffffLL) << 32); 636 } 637 | '-' LCONST '-' LCONST 638 { 639 $$ = (-$2 & 0xffffffffLL) + 640 (($4 & 0xffffLL) << 32); 641 } 642 643 expr: 644 con 645 | expr '+' expr 646 { 647 $$ = $1 + $3; 648 } 649 | expr '-' expr 650 { 651 $$ = $1 - $3; 652 } 653 | expr '*' expr 654 { 655 $$ = $1 * $3; 656 } 657 | expr '/' expr 658 { 659 $$ = $1 / $3; 660 } 661 | expr '%' expr 662 { 663 $$ = $1 % $3; 664 } 665 | expr '<' '<' expr 666 { 667 $$ = $1 << $4; 668 } 669 | expr '>' '>' expr 670 { 671 $$ = $1 >> $4; 672 } 673 | expr '&' expr 674 { 675 $$ = $1 & $3; 676 } 677 | expr '^' expr 678 { 679 $$ = $1 ^ $3; 680 } 681 | expr '|' expr 682 { 683 $$ = $1 | $3; 684 }