1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
18#define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
19
20#include <ostream>
21
22#include "arch/instruction_set.h"
23#include "base/arena_containers.h"
24#include "base/value_object.h"
25
26namespace art {
27
28class CodeGenerator;
29class DexCompilationUnit;
30class HGraph;
31class HInstruction;
32class SlowPathCode;
33
34/**
35 * This class outputs the HGraph in the C1visualizer format.
36 * Note: Currently only works if the compiler is single threaded.
37 */
38struct GeneratedCodeInterval {
39  size_t start;
40  size_t end;
41};
42
43struct SlowPathCodeInfo {
44  const SlowPathCode* slow_path;
45  GeneratedCodeInterval code_interval;
46};
47
48// This information is filled by the code generator. It will be used by the
49// graph visualizer to associate disassembly of the generated code with the
50// instructions and slow paths. We assume that the generated code follows the
51// following structure:
52//   - frame entry
53//   - instructions
54//   - slow paths
55class DisassemblyInformation {
56 public:
57  explicit DisassemblyInformation(ArenaAllocator* allocator)
58      : frame_entry_interval_({0, 0}),
59        instruction_intervals_(std::less<const HInstruction*>(), allocator->Adapter()),
60        slow_path_intervals_(allocator->Adapter()) {}
61
62  void SetFrameEntryInterval(size_t start, size_t end) {
63    frame_entry_interval_ = {start, end};
64  }
65
66  void AddInstructionInterval(HInstruction* instr, size_t start, size_t end) {
67    instruction_intervals_.Put(instr, {start, end});
68  }
69
70  void AddSlowPathInterval(SlowPathCode* slow_path, size_t start, size_t end) {
71    slow_path_intervals_.push_back({slow_path, {start, end}});
72  }
73
74  GeneratedCodeInterval GetFrameEntryInterval() const {
75    return frame_entry_interval_;
76  }
77
78  GeneratedCodeInterval* GetFrameEntryInterval() {
79    return &frame_entry_interval_;
80  }
81
82  const ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>& GetInstructionIntervals() const {
83    return instruction_intervals_;
84  }
85
86  ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>* GetInstructionIntervals() {
87    return &instruction_intervals_;
88  }
89
90  const ArenaVector<SlowPathCodeInfo>& GetSlowPathIntervals() const { return slow_path_intervals_; }
91
92  ArenaVector<SlowPathCodeInfo>* GetSlowPathIntervals() { return &slow_path_intervals_; }
93
94 private:
95  GeneratedCodeInterval frame_entry_interval_;
96  ArenaSafeMap<const HInstruction*, GeneratedCodeInterval> instruction_intervals_;
97  ArenaVector<SlowPathCodeInfo> slow_path_intervals_;
98};
99
100class HGraphVisualizer : public ValueObject {
101 public:
102  HGraphVisualizer(std::ostream* output,
103                   HGraph* graph,
104                   const CodeGenerator& codegen);
105
106  void PrintHeader(const char* method_name) const;
107  void DumpGraph(const char* pass_name, bool is_after_pass, bool graph_in_bad_state) const;
108  void DumpGraphWithDisassembly() const;
109
110 private:
111  std::ostream* const output_;
112  HGraph* const graph_;
113  const CodeGenerator& codegen_;
114
115  DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
116};
117
118}  // namespace art
119
120#endif  // ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
121