OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/il_printer.h" | 5 #include "vm/il_printer.h" |
6 | 6 |
7 #include "vm/intermediate_language.h" | 7 #include "vm/intermediate_language.h" |
8 #include "vm/os.h" | 8 #include "vm/os.h" |
9 | 9 |
10 namespace dart { | 10 namespace dart { |
11 | 11 |
12 | 12 |
13 void BufferFormatter::Print(const char* format, ...) { | 13 void BufferFormatter::Print(const char* format, ...) { |
| 14 va_list args; |
| 15 va_start(args, format); |
| 16 VPrint(format, args); |
| 17 va_end(args); |
| 18 } |
| 19 |
| 20 |
| 21 void BufferFormatter::VPrint(const char* format, va_list args) { |
14 intptr_t available = size_ - position_; | 22 intptr_t available = size_ - position_; |
15 if (available <= 0) return; | 23 if (available <= 0) return; |
16 va_list args; | |
17 va_start(args, format); | |
18 intptr_t written = | 24 intptr_t written = |
19 OS::VSNPrint(buffer_ + position_, available, format, args); | 25 OS::VSNPrint(buffer_ + position_, available, format, args); |
20 if (written >= 0) { | 26 if (written >= 0) { |
21 position_ += (available <= written) ? available : written; | 27 position_ += (available <= written) ? available : written; |
22 } | 28 } |
23 va_end(args); | |
24 } | 29 } |
25 | 30 |
26 | 31 |
27 void FlowGraphPrinter::PrintBlocks() { | 32 void FlowGraphPrinter::PrintBlocks() { |
28 if (!function_.IsNull()) { | 33 if (!function_.IsNull()) { |
29 OS::Print("==== %s\n", function_.ToFullyQualifiedCString()); | 34 OS::Print("==== %s\n", function_.ToFullyQualifiedCString()); |
30 } | 35 } |
31 | 36 |
32 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 37 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
33 // Print the block entry. | 38 // Print the block entry. |
(...skipping 24 matching lines...) Expand all Loading... |
58 | 63 |
59 | 64 |
60 void FlowGraphPrinter::PrintComputation(Computation* comp) { | 65 void FlowGraphPrinter::PrintComputation(Computation* comp) { |
61 char str[120]; | 66 char str[120]; |
62 BufferFormatter f(str, sizeof(str)); | 67 BufferFormatter f(str, sizeof(str)); |
63 comp->PrintTo(&f); | 68 comp->PrintTo(&f); |
64 OS::Print("%s", str); | 69 OS::Print("%s", str); |
65 } | 70 } |
66 | 71 |
67 | 72 |
68 | |
69 void Computation::PrintTo(BufferFormatter* f) const { | 73 void Computation::PrintTo(BufferFormatter* f) const { |
70 f->Print("%s(", DebugName()); | 74 f->Print("%s(", DebugName()); |
71 PrintOperandsTo(f); | 75 PrintOperandsTo(f); |
72 f->Print(")"); | 76 f->Print(")"); |
73 } | 77 } |
74 | 78 |
75 | 79 |
76 void Computation::PrintOperandsTo(BufferFormatter* f) const { | 80 void Computation::PrintOperandsTo(BufferFormatter* f) const { |
77 for (int i = 0; i < InputCount(); ++i) { | 81 for (int i = 0; i < InputCount(); ++i) { |
78 if (i > 0) f->Print(", "); | 82 if (i > 0) f->Print(", "); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 void BranchInstr::PrintTo(BufferFormatter* f) const { | 348 void BranchInstr::PrintTo(BufferFormatter* f) const { |
345 f->Print(" %s ", DebugName()); | 349 f->Print(" %s ", DebugName()); |
346 f->Print("if "); | 350 f->Print("if "); |
347 value()->PrintTo(f); | 351 value()->PrintTo(f); |
348 f->Print(" goto (%d, %d)", | 352 f->Print(" goto (%d, %d)", |
349 true_successor()->block_id(), | 353 true_successor()->block_id(), |
350 false_successor()->block_id()); | 354 false_successor()->block_id()); |
351 } | 355 } |
352 | 356 |
353 | 357 |
| 358 void FlowGraphVisualizer::Print(const char* format, ...) { |
| 359 char str[120]; |
| 360 BufferFormatter f(str, sizeof(str)); |
| 361 f.Print("%*s", 2 * indent_, ""); |
| 362 va_list args; |
| 363 va_start(args, format); |
| 364 f.VPrint(format, args); |
| 365 va_end(args); |
| 366 (*Dart::flow_graph_writer())(str, strlen(str)); |
| 367 } |
| 368 |
| 369 |
| 370 void FlowGraphVisualizer::PrintInstruction(Instruction* instr) { |
| 371 char str[120]; |
| 372 BufferFormatter f(str, sizeof(str)); |
| 373 instr->PrintToVisualizer(&f); |
| 374 f.Print("%s <|@\n", str); |
| 375 (*Dart::flow_graph_writer())(str, strlen(str)); |
| 376 } |
| 377 |
| 378 |
| 379 void FlowGraphVisualizer::PrintFunction() { |
| 380 #define BEGIN(name) \ |
| 381 Print("begin_%s\n", name); \ |
| 382 indent_++; |
| 383 #define END(name) \ |
| 384 Print("end_%s\n", name); \ |
| 385 indent_--; |
| 386 |
| 387 { |
| 388 BEGIN("compilation"); |
| 389 const char* name = function_.ToFullyQualifiedCString(); |
| 390 Print("%s \"%s\"\n", "name", name); |
| 391 Print("%s \"%s\"\n", "method", name); |
| 392 Print("%s %d\n", "date", 0); // Required field. Unused. |
| 393 END("compilation"); |
| 394 } |
| 395 |
| 396 { |
| 397 BEGIN("cfg"); |
| 398 Print("%s \"%s\"\n", "name", "Flow graph builder"); |
| 399 |
| 400 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 401 BEGIN("block"); |
| 402 BlockEntryInstr* entry = block_order_[i]; |
| 403 Print("%s \"B%d\"\n", "name", entry->block_id()); |
| 404 Print("%s %d\n", "from_bci", -1); // Required field. Unused. |
| 405 Print("%s %d\n", "to_bci", -1); // Required field. Unused. |
| 406 |
| 407 Print("predecessors"); |
| 408 for (intptr_t j = 0; j < entry->PredecessorCount(); ++j) { |
| 409 BlockEntryInstr* pred = entry->PredecessorAt(j); |
| 410 Print(" \"B%d\"", pred->block_id()); |
| 411 } |
| 412 Print("\n"); |
| 413 |
| 414 Print("successors"); |
| 415 Instruction* last = entry->last_instruction(); |
| 416 for (intptr_t j = 0; j < last->SuccessorCount(); ++j) { |
| 417 intptr_t next_id = last->SuccessorAt(j)->block_id(); |
| 418 Print(" \"B%d\"", next_id); |
| 419 } |
| 420 Print("\n"); |
| 421 |
| 422 // TODO(fschneider): Use this for exception handlers. |
| 423 Print("xhandlers\n"); |
| 424 |
| 425 // Can be freely used to mark blocks |
| 426 Print("flags\n"); |
| 427 |
| 428 if (entry->dominator() != NULL) { |
| 429 Print("%s \"B%d\"\n", "dominator", entry->dominator()->block_id()); |
| 430 } |
| 431 |
| 432 // TODO(fschneider): Mark blocks with loop nesting level. |
| 433 Print("%s %d\n", "loop_depth", 0); |
| 434 |
| 435 { |
| 436 BEGIN("states"); // Required section. |
| 437 { |
| 438 BEGIN("locals"); // Required section. |
| 439 // TODO(fschneider): Insert phi-instructions here. |
| 440 intptr_t num_phis = 0; |
| 441 Print("%s %d\n", "size", num_phis); |
| 442 END("locals"); |
| 443 } |
| 444 END("states"); |
| 445 } |
| 446 |
| 447 { |
| 448 BEGIN("HIR"); |
| 449 // Print the block entry. |
| 450 Print("0 0 "); // Required fields "bci" and "use". Unused. |
| 451 Instruction* current = block_order_[i]; |
| 452 PrintInstruction(current); |
| 453 current = current->StraightLineSuccessor(); |
| 454 // And all the successors until an exit, branch, or a block entry. |
| 455 while ((current != NULL) && !current->IsBlockEntry()) { |
| 456 Print("0 0 "); |
| 457 PrintInstruction(current); |
| 458 current = current->StraightLineSuccessor(); |
| 459 } |
| 460 BlockEntryInstr* successor = |
| 461 (current == NULL) ? NULL : current->AsBlockEntry(); |
| 462 if (successor != NULL) { |
| 463 Print("0 0 _ Goto B%d <|@\n", successor->block_id()); |
| 464 } |
| 465 END("HIR"); |
| 466 } |
| 467 END("block"); |
| 468 } |
| 469 END("cfg"); |
| 470 } |
| 471 #undef BEGIN |
| 472 #undef END |
| 473 } |
| 474 |
| 475 |
| 476 // === Printing instructions in a visualizer-understandable format: |
| 477 // "result instruction(op1, op2)" where result is a temporary name |
| 478 // or _ for instruction without result. |
| 479 void GraphEntryInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 480 f->Print("_ [graph]"); |
| 481 } |
| 482 |
| 483 |
| 484 void JoinEntryInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 485 f->Print("_ [join]"); |
| 486 } |
| 487 |
| 488 |
| 489 void TargetEntryInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 490 f->Print("_ [target"); |
| 491 if (HasTryIndex()) { |
| 492 f->Print(" catch %d]", try_index()); |
| 493 } else { |
| 494 f->Print("]"); |
| 495 } |
| 496 } |
| 497 |
| 498 |
| 499 void DoInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 500 f->Print("_ "); |
| 501 computation()->PrintTo(f); |
| 502 } |
| 503 |
| 504 |
| 505 void BindInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 506 f->Print("t%d ", temp_index()); |
| 507 computation()->PrintTo(f); |
| 508 } |
| 509 |
| 510 |
| 511 void ReturnInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 512 f->Print("_ %s ", DebugName()); |
| 513 value()->PrintTo(f); |
| 514 } |
| 515 |
| 516 |
| 517 void ThrowInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 518 f->Print("_ %s ", DebugName()); |
| 519 exception()->PrintTo(f); |
| 520 } |
| 521 |
| 522 |
| 523 void ReThrowInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 524 f->Print("_ %s ", DebugName()); |
| 525 exception()->PrintTo(f); |
| 526 f->Print(", "); |
| 527 stack_trace()->PrintTo(f); |
| 528 } |
| 529 |
| 530 |
| 531 void BranchInstr::PrintToVisualizer(BufferFormatter* f) const { |
| 532 f->Print("_ %s ", DebugName()); |
| 533 f->Print("if "); |
| 534 value()->PrintTo(f); |
| 535 f->Print(" goto (B%d, B%d)", |
| 536 true_successor()->block_id(), |
| 537 false_successor()->block_id()); |
| 538 } |
| 539 |
| 540 |
354 } // namespace dart | 541 } // namespace dart |
OLD | NEW |