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