github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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 %} 37 %union { 38 Sym *sym; 39 vlong lval; 40 double dval; 41 char sval[8]; 42 Gen gen; 43 Gen2 gen2; 44 } 45 %left '|' 46 %left '^' 47 %left '&' 48 %left '<' '>' 49 %left '+' '-' 50 %left '*' '/' '%' 51 %token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 52 %token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG 53 %token <lval> LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT 54 %token <lval> LCONST LFP LPC LSB 55 %token <lval> LBREG LLREG LSREG LFREG LMREG LXREG 56 %token <dval> LFCONST 57 %token <sval> LSCONST LSP 58 %token <sym> LNAME LLAB LVAR 59 %type <lval> con con2 expr pointer offset 60 %type <gen> mem imm imm2 reg nam rel rem rim rom omem nmem 61 %type <gen2> nonnon nonrel nonrem rimnon rimrem remrim spec10 spec11 62 %type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 63 %% 64 prog: 65 | prog 66 { 67 stmtline = lineno; 68 } 69 line 70 71 line: 72 LLAB ':' 73 { 74 if($1->value != pc) 75 yyerror("redeclaration of %s", $1->name); 76 $1->value = pc; 77 } 78 line 79 | LNAME ':' 80 { 81 $1->type = LLAB; 82 $1->value = pc; 83 } 84 line 85 | ';' 86 | inst ';' 87 | error ';' 88 89 inst: 90 LNAME '=' expr 91 { 92 $1->type = LVAR; 93 $1->value = $3; 94 } 95 | LVAR '=' expr 96 { 97 if($1->value != $3) 98 yyerror("redeclaration of %s", $1->name); 99 $1->value = $3; 100 } 101 | LTYPE0 nonnon { outcode($1, &$2); } 102 | LTYPE1 nonrem { outcode($1, &$2); } 103 | LTYPE2 rimnon { outcode($1, &$2); } 104 | LTYPE3 rimrem { outcode($1, &$2); } 105 | LTYPE4 remrim { outcode($1, &$2); } 106 | LTYPER nonrel { outcode($1, &$2); } 107 | LTYPED spec1 { outcode($1, &$2); } 108 | LTYPET spec2 { outcode($1, &$2); } 109 | LTYPEC spec3 { outcode($1, &$2); } 110 | LTYPEN spec4 { outcode($1, &$2); } 111 | LTYPES spec5 { outcode($1, &$2); } 112 | LTYPEM spec6 { outcode($1, &$2); } 113 | LTYPEI spec7 { outcode($1, &$2); } 114 | LTYPEXC spec8 { outcode($1, &$2); } 115 | LTYPEX spec9 { outcode($1, &$2); } 116 | LTYPERT spec10 { outcode($1, &$2); } 117 | LTYPEG spec11 { 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 $$.from = $1; 197 $$.to = $3; 198 } 199 | mem ',' con ',' imm2 200 { 201 $$.from = $1; 202 $$.from.scale = $3; 203 $$.to = $5; 204 } 205 206 spec3: /* JMP/CALL */ 207 ',' rom 208 { 209 $$.from = nullgen; 210 $$.to = $2; 211 } 212 | rom 213 { 214 $$.from = nullgen; 215 $$.to = $1; 216 } 217 218 spec4: /* NOP */ 219 nonnon 220 | nonrem 221 222 spec5: /* SHL/SHR */ 223 rim ',' rem 224 { 225 $$.from = $1; 226 $$.to = $3; 227 } 228 | rim ',' rem ':' LLREG 229 { 230 $$.from = $1; 231 $$.to = $3; 232 if($$.from.index != D_NONE) 233 yyerror("dp shift with lhs index"); 234 $$.from.index = $5; 235 } 236 237 spec6: /* MOVW/MOVL */ 238 rim ',' rem 239 { 240 $$.from = $1; 241 $$.to = $3; 242 } 243 | rim ',' rem ':' LSREG 244 { 245 $$.from = $1; 246 $$.to = $3; 247 if($$.to.index != D_NONE) 248 yyerror("dp move with lhs index"); 249 $$.to.index = $5; 250 } 251 252 spec7: 253 rim ',' 254 { 255 $$.from = $1; 256 $$.to = nullgen; 257 } 258 | rim 259 { 260 $$.from = $1; 261 $$.to = nullgen; 262 } 263 | rim ',' rem 264 { 265 $$.from = $1; 266 $$.to = $3; 267 } 268 269 spec8: /* CMPPS/CMPPD */ 270 reg ',' rem ',' con 271 { 272 $$.from = $1; 273 $$.to = $3; 274 $$.to.offset = $5; 275 } 276 277 spec9: /* shufl */ 278 imm ',' rem ',' reg 279 { 280 $$.from = $3; 281 $$.to = $5; 282 if($1.type != D_CONST) 283 yyerror("illegal constant"); 284 $$.to.offset = $1.offset; 285 } 286 287 spec10: /* RET/RETF */ 288 { 289 $$.from = nullgen; 290 $$.to = nullgen; 291 } 292 | imm 293 { 294 $$.from = $1; 295 $$.to = nullgen; 296 } 297 298 spec11: /* GLOBL */ 299 mem ',' imm 300 { 301 $$.from = $1; 302 $$.to = $3; 303 } 304 | mem ',' con ',' imm 305 { 306 $$.from = $1; 307 $$.from.scale = $3; 308 $$.to = $5; 309 } 310 311 rem: 312 reg 313 | mem 314 315 rom: 316 rel 317 | nmem 318 | '*' reg 319 { 320 $$ = $2; 321 } 322 | '*' omem 323 { 324 $$ = $2; 325 } 326 | reg 327 | omem 328 329 rim: 330 rem 331 | imm 332 333 rel: 334 con '(' LPC ')' 335 { 336 $$ = nullgen; 337 $$.type = D_BRANCH; 338 $$.offset = $1 + pc; 339 } 340 | LNAME offset 341 { 342 $$ = nullgen; 343 if(pass == 2) 344 yyerror("undefined label: %s", $1->name); 345 $$.type = D_BRANCH; 346 $$.sym = $1; 347 $$.offset = $2; 348 } 349 | LLAB offset 350 { 351 $$ = nullgen; 352 $$.type = D_BRANCH; 353 $$.sym = $1; 354 $$.offset = $1->value + $2; 355 } 356 357 reg: 358 LBREG 359 { 360 $$ = nullgen; 361 $$.type = $1; 362 } 363 | LFREG 364 { 365 $$ = nullgen; 366 $$.type = $1; 367 } 368 | LLREG 369 { 370 $$ = nullgen; 371 $$.type = $1; 372 } 373 | LMREG 374 { 375 $$ = nullgen; 376 $$.type = $1; 377 } 378 | LSP 379 { 380 $$ = nullgen; 381 $$.type = D_SP; 382 } 383 | LSREG 384 { 385 $$ = nullgen; 386 $$.type = $1; 387 } 388 | LXREG 389 { 390 $$ = nullgen; 391 $$.type = $1; 392 } 393 imm2: 394 '$' con2 395 { 396 $$ = nullgen; 397 $$.type = D_CONST; 398 $$.offset = $2; 399 } 400 401 imm: 402 '$' con 403 { 404 $$ = nullgen; 405 $$.type = D_CONST; 406 $$.offset = $2; 407 } 408 | '$' nam 409 { 410 $$ = $2; 411 $$.index = $2.type; 412 $$.type = D_ADDR; 413 /* 414 if($2.type == D_AUTO || $2.type == D_PARAM) 415 yyerror("constant cannot be automatic: %s", 416 $2.sym->name); 417 */ 418 } 419 | '$' LSCONST 420 { 421 $$ = nullgen; 422 $$.type = D_SCONST; 423 memcpy($$.sval, $2, sizeof($$.sval)); 424 } 425 | '$' LFCONST 426 { 427 $$ = nullgen; 428 $$.type = D_FCONST; 429 $$.dval = $2; 430 } 431 | '$' '(' LFCONST ')' 432 { 433 $$ = nullgen; 434 $$.type = D_FCONST; 435 $$.dval = $3; 436 } 437 | '$' '(' '-' LFCONST ')' 438 { 439 $$ = nullgen; 440 $$.type = D_FCONST; 441 $$.dval = -$4; 442 } 443 | '$' '-' LFCONST 444 { 445 $$ = nullgen; 446 $$.type = D_FCONST; 447 $$.dval = -$3; 448 } 449 450 mem: 451 omem 452 | nmem 453 454 omem: 455 con 456 { 457 $$ = nullgen; 458 $$.type = D_INDIR+D_NONE; 459 $$.offset = $1; 460 } 461 | con '(' LLREG ')' 462 { 463 $$ = nullgen; 464 $$.type = D_INDIR+$3; 465 $$.offset = $1; 466 } 467 | con '(' LSP ')' 468 { 469 $$ = nullgen; 470 $$.type = D_INDIR+D_SP; 471 $$.offset = $1; 472 } 473 | con '(' LSREG ')' 474 { 475 $$ = nullgen; 476 $$.type = D_INDIR+$3; 477 $$.offset = $1; 478 } 479 | con '(' LLREG '*' con ')' 480 { 481 $$ = nullgen; 482 $$.type = D_INDIR+D_NONE; 483 $$.offset = $1; 484 $$.index = $3; 485 $$.scale = $5; 486 checkscale($$.scale); 487 } 488 | con '(' LLREG ')' '(' LLREG '*' con ')' 489 { 490 $$ = nullgen; 491 $$.type = D_INDIR+$3; 492 $$.offset = $1; 493 $$.index = $6; 494 $$.scale = $8; 495 checkscale($$.scale); 496 } 497 | '(' LLREG ')' 498 { 499 $$ = nullgen; 500 $$.type = D_INDIR+$2; 501 } 502 | '(' LSP ')' 503 { 504 $$ = nullgen; 505 $$.type = D_INDIR+D_SP; 506 } 507 | '(' LLREG '*' con ')' 508 { 509 $$ = nullgen; 510 $$.type = D_INDIR+D_NONE; 511 $$.index = $2; 512 $$.scale = $4; 513 checkscale($$.scale); 514 } 515 | '(' LLREG ')' '(' LLREG '*' con ')' 516 { 517 $$ = nullgen; 518 $$.type = D_INDIR+$2; 519 $$.index = $5; 520 $$.scale = $7; 521 checkscale($$.scale); 522 } 523 524 nmem: 525 nam 526 { 527 $$ = $1; 528 } 529 | nam '(' LLREG '*' con ')' 530 { 531 $$ = $1; 532 $$.index = $3; 533 $$.scale = $5; 534 checkscale($$.scale); 535 } 536 537 nam: 538 LNAME offset '(' pointer ')' 539 { 540 $$ = nullgen; 541 $$.type = $4; 542 $$.sym = $1; 543 $$.offset = $2; 544 } 545 | LNAME '<' '>' offset '(' LSB ')' 546 { 547 $$ = nullgen; 548 $$.type = D_STATIC; 549 $$.sym = $1; 550 $$.offset = $4; 551 } 552 553 offset: 554 { 555 $$ = 0; 556 } 557 | '+' con 558 { 559 $$ = $2; 560 } 561 | '-' con 562 { 563 $$ = -$2; 564 } 565 566 pointer: 567 LSB 568 | LSP 569 { 570 $$ = D_AUTO; 571 } 572 | LFP 573 574 con: 575 LCONST 576 | LVAR 577 { 578 $$ = $1->value; 579 } 580 | '-' con 581 { 582 $$ = -$2; 583 } 584 | '+' con 585 { 586 $$ = $2; 587 } 588 | '~' con 589 { 590 $$ = ~$2; 591 } 592 | '(' expr ')' 593 { 594 $$ = $2; 595 } 596 597 con2: 598 LCONST 599 { 600 $$ = $1 & 0xffffffffLL; 601 } 602 | '-' LCONST 603 { 604 $$ = -$2 & 0xffffffffLL; 605 } 606 | LCONST '-' LCONST 607 { 608 $$ = ($1 & 0xffffffffLL) + 609 (($3 & 0xffffLL) << 32); 610 } 611 | '-' LCONST '-' LCONST 612 { 613 $$ = (-$2 & 0xffffffffLL) + 614 (($4 & 0xffffLL) << 32); 615 } 616 617 expr: 618 con 619 | expr '+' expr 620 { 621 $$ = $1 + $3; 622 } 623 | expr '-' expr 624 { 625 $$ = $1 - $3; 626 } 627 | expr '*' expr 628 { 629 $$ = $1 * $3; 630 } 631 | expr '/' expr 632 { 633 $$ = $1 / $3; 634 } 635 | expr '%' expr 636 { 637 $$ = $1 % $3; 638 } 639 | expr '<' '<' expr 640 { 641 $$ = $1 << $4; 642 } 643 | expr '>' '>' expr 644 { 645 $$ = $1 >> $4; 646 } 647 | expr '&' expr 648 { 649 $$ = $1 & $3; 650 } 651 | expr '^' expr 652 { 653 $$ = $1 ^ $3; 654 } 655 | expr '|' expr 656 { 657 $$ = $1 | $3; 658 }