blob: 9878917739e910db42184986ab953c547c76b4de [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
#define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
#include <functional>
#include <ostream>
#include "arch/instruction_set.h"
#include "base/arena_containers.h"
#include "base/macros.h"
#include "base/value_object.h"
#include "block_namer.h"
namespace art HIDDEN {
class CodeGenerator;
class DexCompilationUnit;
class HGraph;
class HInstruction;
class SlowPathCode;
/**
* This class outputs the HGraph in the C1visualizer format.
* Note: Currently only works if the compiler is single threaded.
*/
struct GeneratedCodeInterval {
size_t start;
size_t end;
};
struct SlowPathCodeInfo {
const SlowPathCode* slow_path;
GeneratedCodeInterval code_interval;
};
// This information is filled by the code generator. It will be used by the
// graph visualizer to associate disassembly of the generated code with the
// instructions and slow paths. We assume that the generated code follows the
// following structure:
// - frame entry
// - instructions
// - slow paths
class DisassemblyInformation {
public:
explicit DisassemblyInformation(ArenaAllocator* allocator)
: frame_entry_interval_({0, 0}),
instruction_intervals_(std::less<const HInstruction*>(), allocator->Adapter()),
slow_path_intervals_(allocator->Adapter()) {}
void SetFrameEntryInterval(size_t start, size_t end) {
frame_entry_interval_ = {start, end};
}
void AddInstructionInterval(HInstruction* instr, size_t start, size_t end) {
instruction_intervals_.Put(instr, {start, end});
}
void AddSlowPathInterval(SlowPathCode* slow_path, size_t start, size_t end) {
slow_path_intervals_.push_back({slow_path, {start, end}});
}
GeneratedCodeInterval GetFrameEntryInterval() const {
return frame_entry_interval_;
}
GeneratedCodeInterval* GetFrameEntryInterval() {
return &frame_entry_interval_;
}
const ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>& GetInstructionIntervals() const {
return instruction_intervals_;
}
ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>* GetInstructionIntervals() {
return &instruction_intervals_;
}
const ArenaVector<SlowPathCodeInfo>& GetSlowPathIntervals() const { return slow_path_intervals_; }
ArenaVector<SlowPathCodeInfo>* GetSlowPathIntervals() { return &slow_path_intervals_; }
private:
GeneratedCodeInterval frame_entry_interval_;
ArenaSafeMap<const HInstruction*, GeneratedCodeInterval> instruction_intervals_;
ArenaVector<SlowPathCodeInfo> slow_path_intervals_;
};
class HGraphVisualizer : public ValueObject {
public:
HGraphVisualizer(std::ostream* output,
HGraph* graph,
const CodeGenerator* codegen,
std::optional<std::reference_wrapper<const BlockNamer>> namer = std::nullopt);
void PrintHeader(const char* method_name) const;
void DumpGraph(const char* pass_name, bool is_after_pass, bool graph_in_bad_state) const;
void DumpGraphDebug() const;
void DumpGraphWithDisassembly() const;
// C1visualizer file format does not support inserting arbitrary metadata into a cfg
// file. As a workaround a fake compilation block with the metadata in the name and the
// method attributes is used. Such empty blocks don't break the c1visualizer parser.
static std::string InsertMetaDataAsCompilationBlock(const std::string& meta_data);
static void DumpInstruction(std::ostream* output, HGraph* graph, HInstruction* instruction);
private:
class OptionalDefaultNamer final : public BlockNamer {
public:
explicit OptionalDefaultNamer(std::optional<std::reference_wrapper<const BlockNamer>> inner)
: namer_(inner) {}
std::ostream& PrintName(std::ostream& os, HBasicBlock* blk) const override;
private:
std::optional<std::reference_wrapper<const BlockNamer>> namer_;
};
std::ostream* const output_;
HGraph* const graph_;
const CodeGenerator* codegen_;
OptionalDefaultNamer namer_;
DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
};
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_