| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/il_printer.h" |
| |
| #include "vm/intermediate_language.h" |
| #include "vm/os.h" |
| #include "vm/parser.h" |
| |
| namespace dart { |
| |
| DEFINE_FLAG(bool, print_environments, false, "Print SSA environments."); |
| |
| |
| void BufferFormatter::Print(const char* format, ...) { |
| va_list args; |
| va_start(args, format); |
| VPrint(format, args); |
| va_end(args); |
| } |
| |
| |
| void BufferFormatter::VPrint(const char* format, va_list args) { |
| intptr_t available = size_ - position_; |
| if (available <= 0) return; |
| intptr_t written = |
| OS::VSNPrint(buffer_ + position_, available, format, args); |
| if (written >= 0) { |
| position_ += (available <= written) ? available : written; |
| } |
| } |
| |
| |
| void FlowGraphPrinter::PrintGraph(const char* phase, FlowGraph* flow_graph) { |
| OS::Print("*** BEGIN CFG\n%s\n", phase); |
| FlowGraphPrinter printer(*flow_graph); |
| printer.PrintBlocks(); |
| OS::Print("*** END CFG\n"); |
| } |
| |
| |
| void FlowGraphPrinter::PrintBlock(BlockEntryInstr* block, |
| bool print_locations) { |
| // Print the block entry. |
| PrintOneInstruction(block, print_locations); |
| OS::Print("\n"); |
| // And all the successors in the block. |
| for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| Instruction* current = it.Current(); |
| PrintOneInstruction(current, print_locations); |
| OS::Print("\n"); |
| } |
| } |
| |
| |
| void FlowGraphPrinter::PrintBlocks() { |
| if (!function_.IsNull()) { |
| OS::Print("==== %s\n", function_.ToFullyQualifiedCString()); |
| } |
| |
| for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| PrintBlock(block_order_[i], print_locations_); |
| } |
| } |
| |
| |
| void FlowGraphPrinter::PrintInstruction(Instruction* instr) { |
| PrintOneInstruction(instr, print_locations_); |
| } |
| |
| |
| void FlowGraphPrinter::PrintOneInstruction(Instruction* instr, |
| bool print_locations) { |
| char str[1000]; |
| BufferFormatter f(str, sizeof(str)); |
| instr->PrintTo(&f); |
| if (FLAG_print_environments && (instr->env() != NULL)) { |
| instr->env()->PrintTo(&f); |
| } |
| if (print_locations && (instr->locs() != NULL)) { |
| instr->locs()->PrintTo(&f); |
| } |
| if (instr->lifetime_position() != -1) { |
| OS::Print("%3"Pd": ", instr->lifetime_position()); |
| } |
| if (!instr->IsBlockEntry()) OS::Print(" "); |
| OS::Print("%s", str); |
| } |
| |
| |
| void FlowGraphPrinter::PrintTypeCheck(const ParsedFunction& parsed_function, |
| intptr_t token_pos, |
| Value* value, |
| const AbstractType& dst_type, |
| const String& dst_name, |
| bool eliminated) { |
| const char* compile_type_name = "unknown"; |
| if (value != NULL) { |
| compile_type_name = value->Type()->ToCString(); |
| } |
| OS::Print("%s type check: compile type %s is %s specific than " |
| "type '%s' of '%s'.\n", |
| eliminated ? "Eliminated" : "Generated", |
| compile_type_name, |
| eliminated ? "more" : "not more", |
| String::Handle(dst_type.Name()).ToCString(), |
| dst_name.ToCString()); |
| } |
| |
| |
| void CompileType::PrintTo(BufferFormatter* f) const { |
| f->Print("T{"); |
| f->Print("%s, ", is_nullable_ ? "null" : "not-null"); |
| if (cid_ != kIllegalCid) { |
| const Class& cls = |
| Class::Handle(Isolate::Current()->class_table()->At(cid_)); |
| f->Print("%s, ", String::Handle(cls.Name()).ToCString()); |
| } else { |
| f->Print("?, "); |
| } |
| f->Print("%s}", (type_ != NULL) ? type_->ToCString() : "?"); |
| } |
| |
| |
| const char* CompileType::ToCString() const { |
| char buffer[1024]; |
| BufferFormatter f(buffer, sizeof(buffer)); |
| PrintTo(&f); |
| return Isolate::Current()->current_zone()->MakeCopyOfString(buffer); |
| } |
| |
| |
| |
| |
| static void PrintICData(BufferFormatter* f, const ICData& ic_data) { |
| f->Print(" IC[%"Pd": ", ic_data.NumberOfChecks()); |
| Function& target = Function::Handle(); |
| for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| GrowableArray<intptr_t> class_ids; |
| ic_data.GetCheckAt(i, &class_ids, &target); |
| const intptr_t count = ic_data.GetCountAt(i); |
| if (i > 0) { |
| f->Print(" | "); |
| } |
| for (intptr_t k = 0; k < class_ids.length(); k++) { |
| if (k > 0) { |
| f->Print(", "); |
| } |
| const Class& cls = |
| Class::Handle(Isolate::Current()->class_table()->At(class_ids[k])); |
| f->Print("%s", String::Handle(cls.Name()).ToCString()); |
| } |
| if (count > 0) { |
| f->Print(" #%"Pd, count); |
| } |
| f->Print(" <%p>", static_cast<void*>(target.raw())); |
| } |
| f->Print("]"); |
| } |
| |
| |
| static void PrintUse(BufferFormatter* f, const Definition& definition) { |
| if (definition.is_used()) { |
| if (definition.HasSSATemp()) { |
| f->Print("v%"Pd, definition.ssa_temp_index()); |
| } else if (definition.temp_index() != -1) { |
| f->Print("t%"Pd, definition.temp_index()); |
| } |
| } |
| } |
| |
| |
| void Instruction::PrintTo(BufferFormatter* f) const { |
| if (GetDeoptId() != Isolate::kNoDeoptId) { |
| f->Print("%s:%"Pd"(", DebugName(), GetDeoptId()); |
| } else { |
| f->Print("%s(", DebugName()); |
| } |
| PrintOperandsTo(f); |
| f->Print(")"); |
| } |
| |
| |
| void Instruction::PrintOperandsTo(BufferFormatter* f) const { |
| for (int i = 0; i < InputCount(); ++i) { |
| if (i > 0) f->Print(", "); |
| if (InputAt(i) != NULL) InputAt(i)->PrintTo(f); |
| } |
| } |
| |
| |
| void Definition::PrintTo(BufferFormatter* f) const { |
| PrintUse(f, *this); |
| if (is_used()) { |
| if (HasSSATemp() || (temp_index() != -1)) f->Print(" <- "); |
| } |
| if (GetDeoptId() != Isolate::kNoDeoptId) { |
| f->Print("%s:%"Pd"(", DebugName(), GetDeoptId()); |
| } else { |
| f->Print("%s(", DebugName()); |
| } |
| PrintOperandsTo(f); |
| f->Print(")"); |
| if (range_ != NULL) { |
| f->Print(" "); |
| range_->PrintTo(f); |
| } |
| |
| if (type_ != NULL) { |
| f->Print(" "); |
| type_->PrintTo(f); |
| } |
| } |
| |
| |
| void Definition::PrintOperandsTo(BufferFormatter* f) const { |
| for (int i = 0; i < InputCount(); ++i) { |
| if (i > 0) f->Print(", "); |
| if (InputAt(i) != NULL) InputAt(i)->PrintTo(f); |
| } |
| } |
| |
| |
| void Value::PrintTo(BufferFormatter* f) const { |
| PrintUse(f, *definition()); |
| if ((reaching_type_ != NULL) && |
| (reaching_type_ != definition()->Type())) { |
| f->Print(" "); |
| reaching_type_->PrintTo(f); |
| } |
| } |
| |
| |
| void ConstantInstr::PrintOperandsTo(BufferFormatter* f) const { |
| const char* cstr = value().ToCString(); |
| const char* new_line = strchr(cstr, '\n'); |
| if (new_line == NULL) { |
| f->Print("#%s", cstr); |
| } else { |
| const intptr_t pos = new_line - cstr; |
| char* buffer = Isolate::Current()->current_zone()->Alloc<char>(pos + 1); |
| strncpy(buffer, cstr, pos); |
| buffer[pos] = '\0'; |
| f->Print("#%s\\n...", buffer); |
| } |
| } |
| |
| |
| void ConstraintInstr::PrintOperandsTo(BufferFormatter* f) const { |
| value()->PrintTo(f); |
| f->Print(" ^ "); |
| constraint()->PrintTo(f); |
| } |
| |
| |
| void Range::PrintTo(BufferFormatter* f) const { |
| f->Print("["); |
| min_.PrintTo(f); |
| f->Print(", "); |
| max_.PrintTo(f); |
| f->Print("]"); |
| } |
| |
| |
| const char* Range::ToCString(Range* range) { |
| if (range == NULL) return "[_|_, _|_]"; |
| |
| char buffer[256]; |
| BufferFormatter f(buffer, sizeof(buffer)); |
| range->PrintTo(&f); |
| return Isolate::Current()->current_zone()->MakeCopyOfString(buffer); |
| } |
| |
| |
| void RangeBoundary::PrintTo(BufferFormatter* f) const { |
| switch (kind_) { |
| case kSymbol: |
| f->Print("v%"Pd, reinterpret_cast<Definition*>(value_)->ssa_temp_index()); |
| if (offset_ != 0) f->Print("%+"Pd, offset_); |
| break; |
| case kConstant: |
| if (value_ == kMinusInfinity) { |
| f->Print("-inf"); |
| } else if (value_ == kPlusInfinity) { |
| f->Print("+inf"); |
| } else { |
| f->Print("%"Pd, value_); |
| } |
| break; |
| case kUnknown: |
| f->Print("_|_"); |
| break; |
| } |
| } |
| |
| |
| const char* RangeBoundary::ToCString() const { |
| char buffer[256]; |
| BufferFormatter f(buffer, sizeof(buffer)); |
| PrintTo(&f); |
| return Isolate::Current()->current_zone()->MakeCopyOfString(buffer); |
| } |
| |
| |
| void AssertAssignableInstr::PrintOperandsTo(BufferFormatter* f) const { |
| value()->PrintTo(f); |
| f->Print(", %s, '%s'", |
| dst_type().ToCString(), |
| dst_name().ToCString()); |
| f->Print(" instantiator("); |
| instantiator()->PrintTo(f); |
| f->Print(")"); |
| f->Print(" instantiator_type_arguments("); |
| instantiator_type_arguments()->PrintTo(f); |
| f->Print(")"); |
| } |
| |
| |
| void AssertBooleanInstr::PrintOperandsTo(BufferFormatter* f) const { |
| value()->PrintTo(f); |
| } |
| |
| |
| void ArgumentDefinitionTestInstr::PrintOperandsTo(BufferFormatter* f) const { |
| saved_arguments_descriptor()->PrintTo(f); |
| f->Print(", ?%s @%"Pd"", |
| formal_parameter_name().ToCString(), |
| formal_parameter_index()); |
| } |
| |
| |
| void ClosureCallInstr::PrintOperandsTo(BufferFormatter* f) const { |
| for (intptr_t i = 0; i < ArgumentCount(); ++i) { |
| if (i > 0) f->Print(", "); |
| PushArgumentAt(i)->value()->PrintTo(f); |
| } |
| } |
| |
| |
| void InstanceCallInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s", function_name().ToCString()); |
| for (intptr_t i = 0; i < ArgumentCount(); ++i) { |
| f->Print(", "); |
| PushArgumentAt(i)->value()->PrintTo(f); |
| } |
| if (HasICData()) { |
| PrintICData(f, *ic_data()); |
| } |
| } |
| |
| |
| void PolymorphicInstanceCallInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s", instance_call()->function_name().ToCString()); |
| for (intptr_t i = 0; i < ArgumentCount(); ++i) { |
| f->Print(", "); |
| PushArgumentAt(i)->value()->PrintTo(f); |
| } |
| PrintICData(f, ic_data()); |
| } |
| |
| |
| void StrictCompareInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(kind())); |
| left()->PrintTo(f); |
| f->Print(", "); |
| right()->PrintTo(f); |
| } |
| |
| |
| void EqualityCompareInstr::PrintOperandsTo(BufferFormatter* f) const { |
| left()->PrintTo(f); |
| f->Print(" %s ", Token::Str(kind())); |
| right()->PrintTo(f); |
| if (HasICData()) { |
| PrintICData(f, *ic_data()); |
| } |
| } |
| |
| |
| void StaticCallInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s ", String::Handle(function().name()).ToCString()); |
| for (intptr_t i = 0; i < ArgumentCount(); ++i) { |
| if (i > 0) f->Print(", "); |
| PushArgumentAt(i)->value()->PrintTo(f); |
| } |
| } |
| |
| |
| void LoadLocalInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s", local().name().ToCString()); |
| } |
| |
| |
| void StoreLocalInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", local().name().ToCString()); |
| value()->PrintTo(f); |
| } |
| |
| |
| void NativeCallInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s", native_name().ToCString()); |
| } |
| |
| |
| void GuardFieldInstr::PrintOperandsTo(BufferFormatter* f) const { |
| const char* expected = "?"; |
| if (field().guarded_cid() != kIllegalCid) { |
| const Class& cls = Class::Handle( |
| Isolate::Current()->class_table()->At(field().guarded_cid())); |
| expected = String::Handle(cls.Name()).ToCString(); |
| } |
| |
| f->Print("%s [%s %s], ", |
| String::Handle(field().name()).ToCString(), |
| field().is_nullable() ? "nullable" : "non-nullable", |
| expected); |
| value()->PrintTo(f); |
| } |
| |
| |
| void StoreInstanceFieldInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s {%"Pd"}, ", |
| String::Handle(field().name()).ToCString(), |
| field().Offset()); |
| instance()->PrintTo(f); |
| f->Print(", "); |
| value()->PrintTo(f); |
| } |
| |
| |
| void IfThenElseInstr::PrintOperandsTo(BufferFormatter* f) const { |
| left()->PrintTo(f); |
| f->Print(" %s ", Token::Str(kind_)); |
| right()->PrintTo(f); |
| f->Print(" ? %"Pd" : %"Pd, |
| if_true_, |
| if_false_); |
| } |
| |
| |
| void LoadStaticFieldInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s", String::Handle(field().name()).ToCString()); |
| } |
| |
| |
| void StoreStaticFieldInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", String::Handle(field().name()).ToCString()); |
| value()->PrintTo(f); |
| } |
| |
| |
| void InstanceOfInstr::PrintOperandsTo(BufferFormatter* f) const { |
| value()->PrintTo(f); |
| f->Print(" %s %s", |
| negate_result() ? "ISNOT" : "IS", |
| String::Handle(type().Name()).ToCString()); |
| f->Print(" instantiator("); |
| instantiator()->PrintTo(f); |
| f->Print(")"); |
| f->Print(" type-arg("); |
| instantiator_type_arguments()->PrintTo(f); |
| f->Print(")"); |
| } |
| |
| |
| void RelationalOpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(kind())); |
| left()->PrintTo(f); |
| f->Print(", "); |
| right()->PrintTo(f); |
| if (HasICData()) { |
| PrintICData(f, *ic_data()); |
| } |
| } |
| |
| |
| void AllocateObjectInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s", Class::Handle(constructor().Owner()).ToCString()); |
| for (intptr_t i = 0; i < ArgumentCount(); i++) { |
| f->Print(", "); |
| PushArgumentAt(i)->value()->PrintTo(f); |
| } |
| } |
| |
| |
| void AllocateObjectWithBoundsCheckInstr::PrintOperandsTo( |
| BufferFormatter* f) const { |
| f->Print("%s", Class::Handle(constructor().Owner()).ToCString()); |
| for (intptr_t i = 0; i < InputCount(); i++) { |
| f->Print(", "); |
| InputAt(i)->PrintTo(f); |
| } |
| } |
| |
| |
| void CreateArrayInstr::PrintOperandsTo(BufferFormatter* f) const { |
| for (int i = 0; i < ArgumentCount(); ++i) { |
| if (i != 0) f->Print(", "); |
| PushArgumentAt(i)->value()->PrintTo(f); |
| } |
| if (ArgumentCount() > 0) f->Print(", "); |
| element_type()->PrintTo(f); |
| } |
| |
| |
| void CreateClosureInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s", function().ToCString()); |
| for (intptr_t i = 0; i < ArgumentCount(); ++i) { |
| if (i > 0) f->Print(", "); |
| PushArgumentAt(i)->value()->PrintTo(f); |
| } |
| } |
| |
| |
| void LoadFieldInstr::PrintOperandsTo(BufferFormatter* f) const { |
| value()->PrintTo(f); |
| f->Print(", %"Pd, offset_in_bytes()); |
| |
| if (field_name_ != NULL) { |
| f->Print(" {%s}", field_name_); |
| } |
| |
| if (field() != NULL) { |
| const char* expected = "?"; |
| if (field()->guarded_cid() != kIllegalCid) { |
| const Class& cls = Class::Handle( |
| Isolate::Current()->class_table()->At(field()->guarded_cid())); |
| expected = String::Handle(cls.Name()).ToCString(); |
| } |
| |
| f->Print(" [%s %s]", |
| field()->is_nullable() ? "nullable" : "non-nullable", |
| expected); |
| } |
| |
| f->Print(", immutable=%d", immutable_); |
| } |
| |
| |
| void StoreVMFieldInstr::PrintOperandsTo(BufferFormatter* f) const { |
| dest()->PrintTo(f); |
| f->Print(", %"Pd", ", offset_in_bytes()); |
| value()->PrintTo(f); |
| } |
| |
| |
| void InstantiateTypeArgumentsInstr::PrintOperandsTo(BufferFormatter* f) const { |
| const String& type_args = String::Handle(type_arguments().Name()); |
| f->Print("%s, ", type_args.ToCString()); |
| instantiator()->PrintTo(f); |
| } |
| |
| |
| void ExtractConstructorTypeArgumentsInstr::PrintOperandsTo( |
| BufferFormatter* f) const { |
| const String& type_args = String::Handle(type_arguments().Name()); |
| f->Print("%s, ", type_args.ToCString()); |
| instantiator()->PrintTo(f); |
| } |
| |
| |
| void AllocateContextInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%"Pd"", num_context_variables()); |
| } |
| |
| |
| void CatchEntryInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, %s", |
| exception_var().name().ToCString(), |
| stacktrace_var().name().ToCString()); |
| } |
| |
| |
| void BinarySmiOpInstr::PrintTo(BufferFormatter* f) const { |
| Definition::PrintTo(f); |
| f->Print(" %co", overflow_ ? '+' : '-'); |
| f->Print(" %ct", is_truncating() ? '+' : '-'); |
| } |
| |
| |
| void BinarySmiOpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(op_kind())); |
| left()->PrintTo(f); |
| f->Print(", "); |
| right()->PrintTo(f); |
| } |
| |
| |
| void BinaryDoubleOpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(op_kind())); |
| left()->PrintTo(f); |
| f->Print(", "); |
| right()->PrintTo(f); |
| } |
| |
| |
| void BinaryFloat32x4OpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(op_kind())); |
| left()->PrintTo(f); |
| f->Print(", "); |
| right()->PrintTo(f); |
| } |
| |
| |
| void Float32x4ShuffleInstr::PrintOperandsTo(BufferFormatter* f) const { |
| // TODO(johnmccutchan): Add proper string enumeration of shuffle. |
| f->Print("SHUFFLE "); |
| value()->PrintTo(f); |
| } |
| |
| |
| void Float32x4ZeroInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("ZERO "); |
| } |
| |
| |
| void Float32x4SplatInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("SPLAT "); |
| value()->PrintTo(f); |
| } |
| |
| |
| void Float32x4ConstructorInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("Float32x4("); |
| value0()->PrintTo(f); |
| f->Print(", "); |
| value1()->PrintTo(f); |
| f->Print(", "); |
| value2()->PrintTo(f); |
| f->Print(", "); |
| value3()->PrintTo(f); |
| f->Print(")"); |
| } |
| |
| |
| void BinaryMintOpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(op_kind())); |
| left()->PrintTo(f); |
| f->Print(", "); |
| right()->PrintTo(f); |
| } |
| |
| |
| void ShiftMintOpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(op_kind())); |
| left()->PrintTo(f); |
| f->Print(", "); |
| right()->PrintTo(f); |
| } |
| |
| |
| void UnaryMintOpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(op_kind())); |
| value()->PrintTo(f); |
| } |
| |
| |
| void UnarySmiOpInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", Token::Str(op_kind())); |
| value()->PrintTo(f); |
| } |
| |
| |
| void CheckClassInstr::PrintOperandsTo(BufferFormatter* f) const { |
| value()->PrintTo(f); |
| PrintICData(f, unary_checks()); |
| if (null_check()) { |
| f->Print(" nullcheck"); |
| } |
| } |
| |
| |
| void InvokeMathCFunctionInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%s, ", MethodRecognizer::KindToCString(recognized_kind_)); |
| Definition::PrintOperandsTo(f); |
| } |
| |
| |
| void GraphEntryInstr::PrintTo(BufferFormatter* f) const { |
| const GrowableArray<Definition*>& defns = initial_definitions_; |
| f->Print("B%"Pd"[graph]", block_id()); |
| if (defns.length() > 0) { |
| f->Print(" {"); |
| for (intptr_t i = 0; i < defns.length(); ++i) { |
| Definition* def = defns[i]; |
| f->Print("\n "); |
| def->PrintTo(f); |
| } |
| f->Print("\n}"); |
| } |
| } |
| |
| |
| void JoinEntryInstr::PrintTo(BufferFormatter* f) const { |
| f->Print("B%"Pd"[join] pred(", block_id()); |
| for (intptr_t i = 0; i < predecessors_.length(); ++i) { |
| if (i > 0) f->Print(", "); |
| f->Print("B%"Pd, predecessors_[i]->block_id()); |
| } |
| f->Print(")"); |
| if (phis_ != NULL) { |
| f->Print(" {"); |
| for (intptr_t i = 0; i < phis_->length(); ++i) { |
| if ((*phis_)[i] == NULL) continue; |
| f->Print("\n "); |
| (*phis_)[i]->PrintTo(f); |
| } |
| f->Print("\n}"); |
| } |
| if (HasParallelMove()) { |
| f->Print(" "); |
| parallel_move()->PrintTo(f); |
| } |
| } |
| |
| |
| void PhiInstr::PrintTo(BufferFormatter* f) const { |
| f->Print("v%"Pd" <- phi(", ssa_temp_index()); |
| for (intptr_t i = 0; i < inputs_.length(); ++i) { |
| if (inputs_[i] != NULL) inputs_[i]->PrintTo(f); |
| if (i < inputs_.length() - 1) f->Print(", "); |
| } |
| f->Print(")"); |
| if (is_alive()) { |
| f->Print(" alive"); |
| } else { |
| f->Print(" dead"); |
| } |
| if (range_ != NULL) { |
| f->Print(" "); |
| range_->PrintTo(f); |
| } |
| if (type_ != NULL) { |
| f->Print(" "); |
| type_->PrintTo(f); |
| } |
| } |
| |
| |
| void ParameterInstr::PrintOperandsTo(BufferFormatter* f) const { |
| f->Print("%"Pd, index()); |
| } |
| |
| |
| void TargetEntryInstr::PrintTo(BufferFormatter* f) const { |
| f->Print("B%"Pd"[target]", block_id()); |
| if (HasParallelMove()) { |
| f->Print(" "); |
| parallel_move()->PrintTo(f); |
| } |
| } |
| |
| |
| void CatchBlockEntryInstr::PrintTo(BufferFormatter* f) const { |
| f->Print("B%"Pd"[target catch %"Pd"]", block_id(), catch_try_index()); |
| if (HasParallelMove()) { |
| f->Print(" "); |
| parallel_move()->PrintTo(f); |
| } |
| } |
| |
| |
| void PushArgumentInstr::PrintOperandsTo(BufferFormatter* f) const { |
| value()->PrintTo(f); |
| } |
| |
| |
| void GotoInstr::PrintTo(BufferFormatter* f) const { |
| if (HasParallelMove()) { |
| parallel_move()->PrintTo(f); |
| f->Print(" "); |
| } |
| if (GetDeoptId() != Isolate::kNoDeoptId) { |
| f->Print("goto:%"Pd" %"Pd"", GetDeoptId(), successor()->block_id()); |
| } else { |
| f->Print("goto: %"Pd"", successor()->block_id()); |
| } |
| } |
| |
| |
| void BranchInstr::PrintTo(BufferFormatter* f) const { |
| f->Print("%s ", DebugName()); |
| f->Print("if "); |
| comparison()->PrintTo(f); |
| |
| f->Print(" goto (%"Pd", %"Pd")", |
| true_successor()->block_id(), |
| false_successor()->block_id()); |
| } |
| |
| |
| void ParallelMoveInstr::PrintTo(BufferFormatter* f) const { |
| f->Print("%s ", DebugName()); |
| for (intptr_t i = 0; i < moves_.length(); i++) { |
| if (i != 0) f->Print(", "); |
| moves_[i]->dest().PrintTo(f); |
| f->Print(" <- "); |
| moves_[i]->src().PrintTo(f); |
| } |
| } |
| |
| |
| void Environment::PrintTo(BufferFormatter* f) const { |
| f->Print(" env={ "); |
| int arg_count = 0; |
| for (intptr_t i = 0; i < values_.length(); ++i) { |
| if (i > 0) f->Print(", "); |
| if (values_[i]->definition()->IsPushArgument()) { |
| f->Print("a%d", arg_count++); |
| } else { |
| values_[i]->PrintTo(f); |
| } |
| if ((locations_ != NULL) && !locations_[i].IsInvalid()) { |
| f->Print(" ["); |
| locations_[i].PrintTo(f); |
| f->Print("]"); |
| } |
| } |
| f->Print(" }"); |
| if (outer_ != NULL) outer_->PrintTo(f); |
| } |
| |
| } // namespace dart |