blob: d3983bf3ca0a4075a9656d6777c26e67d8a92048 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.
//
// Provides the Basic-Block Graph representation and APIs.
//
// See http://en.wikipedia.org/wiki/Basic_block for a brief discussion of
// basic blocks, their uses, and related terminology.
//
// TODO(rogerm): Unify the representation and idioms for attributes of
// block, basic-blocks, and labels. Blocks and labels are similar but
// not the same, and basic-blocks just has "is_padding" as a boolean.
#ifndef SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_H_
#define SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_H_
#include "base/strings/string_piece.h"
#include "syzygy/assm/assembler.h"
#include "syzygy/block_graph/block_graph.h"
#include "syzygy/block_graph/tags.h"
#include "syzygy/common/align.h"
#include "syzygy/core/disassembler_util.h"
#include "distorm.h" // NOLINT
namespace block_graph {
// Forward declarations.
class BasicBlock;
class BasicBlockSubGraph;
class BasicCodeBlock;
class BasicDataBlock;
class Instruction;
class Successor;
// Represents a reference from one basic-block to another basic-block or to
// another code- or data-block altogether.
class BasicBlockReference {
public:
typedef BlockGraph::ReferenceType ReferenceType;
typedef BlockGraph::Block Block;
typedef BlockGraph::Offset Offset;
typedef BlockGraph::Size Size;
enum ReferredType {
REFERRED_TYPE_UNKNOWN,
REFERRED_TYPE_BLOCK,
REFERRED_TYPE_BASIC_BLOCK,
// This enum value should always be last.
MAX_REFERRED_TYPE,
};
// Default constructor; needed for storage in stl containers.
BasicBlockReference();
// Create a reference to a block.
//
// @param type type of reference.
// @param size size of reference.
// @param block the referenced block.
// @param offset offset of reference into @p block.
// @param base base of the reference within @p block.
BasicBlockReference(ReferenceType type,
Size size,
Block* block,
Offset offset,
Offset base);
// Create a reference to a basic-block.
//
// @param type type of reference.
// @param size size of reference.
// @param basic_block the referenced basic block.
BasicBlockReference(ReferenceType type,
Size size,
BasicBlock* basic_block);
// Creates a reference to the same destination as @p ref, but with
// a potentially new type and size.
//
// @param type type of reference.
// @param size size of reference.
// @param basic_block the destination for the new reference.
BasicBlockReference(ReferenceType type,
Size size,
const BasicBlockReference& ref);
// Copy constructor.
BasicBlockReference(const BasicBlockReference& other);
// Accessors.
// @{
// Retrieves the type of block (macro or basic) that it referenced.
ReferredType referred_type() const { return referred_type_; }
// Retrieves the type reference (absolute or relative) for this reference.
ReferenceType reference_type() const { return reference_type_; }
// Retrieves the size of the reference.
Size size() const { return size_; }
// Retrieves the referenced block or NULL if this reference does not
// refer to a block.
Block* block() const {
return referred_type_ == REFERRED_TYPE_BLOCK ? referred_block_ : NULL;
}
// Retrieves the referenced basic-block or NULL if this reference does not
// refer to a basic block.
BasicBlock* basic_block() const {
return referred_type_ == REFERRED_TYPE_BASIC_BLOCK ?
referred_basic_block_ : NULL;
}
// Retrieves the offset into the referenced macro- or basic-block.
Offset offset() const { return offset_; }
// Retrieves the base offset to which this reference refers.
Offset base() const { return base_; }
// @}
// Compare this BasicBlockReferences with another for equality.
bool operator==(const BasicBlockReference& other) const {
return (referred_type_ == other.referred_type_ &&
reference_type_ == other.reference_type_ &&
size_ == other.size_ &&
referred_block_ == other.referred_block_ &&
offset_ == other.offset_);
}
// Test if this reference has been initialized to refer to something.
bool IsValid() const {
return size_ != 0 && referred_block_ != NULL;
}
// @returns the tags associated with this object.
TagSet& tags() { return tags_; }
const TagSet& tags() const { return tags_; }
protected:
// Denotes whether this reference is to a block or basic block.
ReferredType referred_type_;
// The type of this reference.
ReferenceType reference_type_;
// The size of this reference.
// Absolute references are always pointer wide, but PC-relative
// references can be 1, 2 or 4 bytes wide, which affects their range.
Size size_;
// The block or basic-block that is referenced.
union {
Block* referred_block_;
BasicBlock* referred_basic_block_;
};
// The offset into the referenced block or basic-block. This may or may not
// end up referring into the target block's byte range.
Offset offset_;
// The base of the reference, as an offset into the referenced block or
// basic-block. This must be a location strictly within the target block's
// byte range.
Offset base_;
// The tags that are applied to this object.
TagSet tags_;
};
// This class keeps track of a reference from an external block to a basic
// block. Instances of this only make sense in the context of a given basic
// block breakdown.
class BasicBlockReferrer {
public:
typedef BlockGraph::Block Block;
typedef BlockGraph::Offset Offset;
// Create an empty (invalid) BasicBlockReferrer.
BasicBlockReferrer();
// Create a BasicBlockReferrer which tracks that an external block makes
// reference to this basic block.
// @param block The block which refers to this basic block.
// @param offset The offset in the block at which the reference occurs.
BasicBlockReferrer(const Block* block, Offset offset);
// Create a copy of the @p other BasicBlockReferrer.
// @param other A basic block referrer record to be copy constructed.
BasicBlockReferrer(const BasicBlockReferrer& other);
// Returns the block which refers to this basic block, or NULL.
const Block* block() const {
return referrer_;
}
// Returns the offset in the referrer at which the reference to
// the basic block occurs.
Offset offset() const { return offset_; }
// Returns whether or not this is a valid basic block referrer object.
bool IsValid() const;
// Equality comparator.
bool operator==(const BasicBlockReferrer& other) const {
return referrer_ == other.referrer_ && offset_ == other.offset_;
}
// Less-than comparator. Useful for putting BasicBlockReferrers into
// ordered containers.
struct CompareAsLess {
bool operator()(const BasicBlockReferrer& lhs,
const BasicBlockReferrer& rhs) const {
return lhs.referrer_ < rhs.referrer_ ||
(lhs.referrer_ == rhs.referrer_ && lhs.offset_ < rhs.offset_);
}
};
protected:
// The referring block.
const Block* referrer_;
// The source offset in the block where the reference occurs.
Offset offset_;
};
// Represents an instruction in a basic-block.
class Instruction {
public:
typedef BlockGraph::Size Size;
typedef BlockGraph::Offset Offset;
typedef BlockGraph::Block::SourceRange SourceRange;
typedef _DInst Representation;
typedef std::map<Offset, BasicBlockReference> BasicBlockReferenceMap;
// The maximum size (in bytes) of an x86 instruction, per specs.
static const uint32_t kMaxSize = assm::kMaxInstructionLength;
// A default constructed Instruction will be a single byte NOP.
Instruction();
// Copy constructor.
Instruction(const Instruction& other);
// Factory to construct an initialized Instruction instance from a buffer.
// @param buf the data comprising the instruction.
// @param len the maximum length (in bytes) of @p buf to consume
// @returns true on success, false otherwise.
static bool FromBuffer(const uint8_t* buf, uint32_t len, Instruction* inst);
// Accessors.
// @{
const Representation& representation() const { return representation_; }
Representation& representation() { return representation_; }
const BasicBlockReferenceMap& references() const { return references_; }
BasicBlockReferenceMap& references() { return references_; }
SourceRange source_range() const { return source_range_; }
void set_source_range(const SourceRange& source_range) {
source_range_ = source_range;
}
const BlockGraph::Label& label() const { return label_; }
void set_label(const BlockGraph::Label& label) { label_ = label; }
bool has_label() const { return label_.IsValid(); }
uint16_t opcode() const { return representation_.opcode; }
Size size() const { return representation_.size; }
const uint8_t* data() const { return data_; }
uint8_t* GetMutableData() { return data_; }
/// @}
// @name Helper functions.
// @{
bool IsNop() const { return core::IsNop(representation_); }
bool IsCall() const { return core::IsCall(representation_); }
bool IsReturn() const { return core::IsReturn(representation_); }
bool IsSystemCall() const { return core::IsSystemCall(representation_); }
bool IsConditionalBranch() const {
return core::IsConditionalBranch(representation_);
}
bool IsUnconditionalBranch() const {
return core::IsUnconditionalBranch(representation_);
}
bool IsBranch() const { return core::IsBranch(representation_); }
bool HasPcRelativeOperand(int operand_index) const {
return core::HasPcRelativeOperand(representation_, operand_index);
}
bool IsControlFlow() const { return core::IsControlFlow(representation_); }
bool IsImplicitControlFlow() const {
return core::IsImplicitControlFlow(representation_);
}
bool IsInterrupt() const { return core::IsInterrupt(representation_); }
bool IsDebugInterrupt() const {
return core::IsDebugInterrupt(representation_);
}
bool CallsNonReturningFunction() const;
// @}
// Returns the mnemonic name for this instruction.
const char* GetName() const;
// Dump a text representation of this instruction.
// @param buf receives the text representation.
// @returns true if this instruction was successfully dumped, false otherwise.
bool ToString(std::string* buf) const;
// Returns the maximum size required to serialize this instruction.
Size GetMaxSize() const { return representation_.size; }
// Add a reference @p ref to this instruction at @p offset. If the reference
// is to a basic block, also update that basic blocks referrer set.
bool SetReference(Offset offset, const BasicBlockReference& ref);
// Finds the reference, if any, for @p operand_index of this instruction.
// @param operand_index the desired operand, in the range 0-3.
// @param reference on success returns the reference.
// @returns true iff @p operand_index exists and has a reference.
bool FindOperandReference(size_t operand_index,
BasicBlockReference* reference) const;
// Helper function to invert a conditional branching opcode.
static bool InvertConditionalBranchOpcode(uint16_t* opcode);
// Returns true if the given PC-relative or indirect-memory call instruction
// is to a non-returning function. The block (and offset into it) being
// directly referenced by the call need to be provided explicitly.
static bool IsCallToNonReturningFunction(const Representation& inst,
const BlockGraph::Block* target,
Offset offset);
// @returns the tags associated with this object.
TagSet& tags() { return tags_; }
const TagSet& tags() const { return tags_; }
protected:
// Construct an instruction from its parsed representation and underlying
// memory buffer.
Instruction(const _DInst& repr, const uint8_t* data);
// The internal representation of this instruction.
Representation representation_;
// Captures the references (if any) that this instruction makes to another
// basic block or macro block.
BasicBlockReferenceMap references_;
// The label, if any, associated with this instruction.
BlockGraph::Label label_;
// The source range, if any, associated with this instruction.
SourceRange source_range_;
// The data associated with this instruction.
uint8_t data_[kMaxSize];
// The tags that are applied to this object.
TagSet tags_;
};
// This class represents a control flow transfer to a basic block, which
// includes both the target basic block as well as the condition on which
// control flows to that basic block.
class Successor {
public:
typedef core::AbsoluteAddress AbsoluteAddress;
typedef BlockGraph::Offset Offset;
typedef BlockGraph::Size Size;
typedef BlockGraph::Block::SourceRange SourceRange;
typedef std::map<Offset, BasicBlockReference> BasicBlockReferenceMap;
// The op-code of an binary instruction.
typedef uint16_t OpCode;
// The set of logical branching flow a successor may embody.
enum Condition {
// Sentinel value denoting an invalid branch condition.
kInvalidCondition = -1,
// These correspond to the conditional branch instructions.
// @{
kConditionAbove = assm::kAbove, // JA and JNBE.
kConditionAboveOrEqual = assm::kAboveEqual, // JAE, JNB and JNC.
kConditionBelow = assm::kBelow, // JB, JNAE and JC.
kConditionBelowOrEqual = assm::kBelowEqual, // JBE and JNA.
kConditionEqual = assm::kEqual, // JE and JZ.
kConditionGreater = assm::kGreater, // JG and JNLE.
kConditionGreaterOrEqual = assm::kGreaterEqual, // JGE and JNL.
kConditionLess = assm::kLess, // JL and JNGE.
kConditionLessOrEqual = assm::kLessEqual, // JLE and JNG.
kConditionNotEqual = assm::kNotEqual, // JNZ, JNE.
kConditionNotOverflow = assm::kNoOverflow, // JNO.
kConditionNotParity = assm::kParityOdd, // JNP and JPO.
kConditionNotSigned = assm::kNotSign, // JNS.
kConditionOverflow = assm::kOverflow, // JO.
kConditionParity = assm::kParityEven, // JP and JPE.
kConditionSigned = assm::kSign, // JS.
// Definitions for the bounding values for the conditional branches.
// Note: that the maximum must be defined here to let all subsequent
// enum values be properly incremented.
kMinConditionalBranch = assm::kMinConditionCode,
kMaxConditionalBranch = assm::kMaxConditionCode,
// Unconditional control flow instructions.
// @{
kConditionTrue, // JMP.
// @}
// Sentinels for the largest successor condition values.
kMaxCondition,
};
// Constructors.
// @{
// Creates a dangling successor.
//
// This needs to exist so that successors can be stored in STL containers.
Successor();
// Creates a successor that resolves to a known block or basic block.
//
// @param condition the branching condition for this successor.
// @param target the basic block to which this successor refers.
// @param offset the offset in the original block at which the instruction(s)
// for this successor are located.
// @param size the length (in bytes) that the instructions for this successor
// occupies in the original block.
Successor(Condition condition,
const BasicBlockReference& target,
Size instruction_size);
// Copy-constructor.
Successor(const Successor& other);
// @}
// Accessors.
// @{
// The type of branch represented by this successor.
Condition condition() const { return condition_; }
BasicBlockReference reference() const { return reference_; }
void set_reference(const BasicBlockReference& reference) {
reference_ = reference;
}
SourceRange source_range() const { return source_range_; }
void set_source_range(const SourceRange& source_range) {
source_range_ = source_range;
}
Size instruction_size() const { return instruction_size_; }
const BlockGraph::Label& label() const { return label_; }
void set_label(const BlockGraph::Label& label) { label_ = label; }
bool has_label() const { return label_.IsValid(); }
// @}
// Set the target reference @p ref for this successor. If @p ref refers
// to a basic block, also update that basic block's referrer set.
bool SetReference(const BasicBlockReference& ref);
// Get the branch type that corresponds to the given @p op_code.
// @returns kInvalidCondition if @p op_code isn't a recognized branch
// instruction.
static Condition OpCodeToCondition(OpCode op_code);
// Get the condition that represents the inversion of the given @p condition.
//
// @p condition the condition to invert.
// @returns kInvalidCondition if @p condition is not invertible.
static Condition InvertCondition(Condition condition);
// Returns a textual description of this successor.
std::string ToString() const;
// @returns the tags associated with this object.
TagSet& tags() { return tags_; }
const TagSet& tags() const { return tags_; }
protected:
// The type of branch represented by this successor.
Condition condition_;
// The destination for this successor.
BasicBlockReference reference_;
// The label, if any, associated with this successor.
BlockGraph::Label label_;
// The source range, if any, associated with this successor.
SourceRange source_range_;
// The size of the instruction this successor is derived from,
// or zero if it's synthesized or added post-decomposition.
Size instruction_size_;
// The tags that are applied to this object.
TagSet tags_;
};
// An indivisible portion of code or data within a code block.
//
// See http://en.wikipedia.org/wiki/Basic_block for a general description of
// the properties. This has been augmented with the ability to also represent
// blocks of data that are tightly coupled with the code (jump and case tables
// for example).
class BasicBlock {
public:
enum BasicBlockType {
BASIC_CODE_BLOCK,
BASIC_DATA_BLOCK,
BASIC_END_BLOCK,
// This must be last.
BASIC_BLOCK_TYPE_MAX
};
typedef BlockGraph::BlockId BlockId;
typedef std::list<Instruction> Instructions;
typedef BlockGraph::Size Size;
typedef std::list<Successor> Successors;
typedef BlockGraph::Offset Offset;
// The collection of references this basic block makes to other basic
// blocks, keyed by the references offset relative to the start of this
// basic block.
typedef Instruction::BasicBlockReferenceMap BasicBlockReferenceMap;
// The set of the blocks that have a reference to this basic block.
// This is keyed on block and source offset (not destination offset),
// to allow us to easily locate and remove the back-references on change or
// deletion.
typedef std::set<BasicBlockReferrer, BasicBlockReferrer::CompareAsLess>
BasicBlockReferrerSet;
// This offset is used to denote that an instruction, successor, or
// basic block has been synthesized and has no corresponding image in
// the original block.
static const Offset kNoOffset;
// Virtual destructor to allow subclassing.
virtual ~BasicBlock();
// Return a textual label for a basic block type.
static const char* BasicBlockTypeToString(BasicBlockType type);
// Accessors.
// @{
BlockId id() const { return id_; }
BasicBlockType type() const { return type_; }
const std::string& name() const { return name_; }
bool is_padding() const { return is_padding_; }
size_t alignment() const { return alignment_; }
void set_alignment(size_t alignment) {
DCHECK_LE(1u, alignment_);
DCHECK(common::IsPowerOfTwo(alignment));
alignment_ = alignment;
}
Offset offset() const { return offset_; }
void set_offset(Offset offset) { offset_ = offset; }
const BasicBlockReferrerSet& referrers() const { return referrers_; }
BasicBlockReferrerSet& referrers() { return referrers_; }
// @}
// Returns true iff this basic block is a valid block (i.e., it
// is a BASIC_DATA_BLOCK the contains data XOR a BASIC_CODE_BLOCK that
// contains instructions and/or successors.
virtual bool IsValid() const = 0;
// Mark this basic block as padding/unreachable. This transformation is uni-
// directional; the block should be considered immutable once this is called.
void MarkAsPadding();
// @returns the tags associated with this object.
TagSet& tags() { return tags_; }
const TagSet& tags() const { return tags_; }
// @return the subgraph associated with this object
BasicBlockSubGraph* subgraph() const { return subgraph_; }
protected:
// Initialize a basic block.
// @param subgraph The subgraph that owns this basic block.
// @param name A textual identifier for this basic block.
// @param id The unique identifier for this basic block.
// @param type The disposition (code, data, padding) of this basic block.
BasicBlock(BasicBlockSubGraph* subgraph,
const base::StringPiece& name,
BlockId id,
BasicBlockType type);
// The unique id for this basic block.
BlockId id_;
// The type of this basic block.
BasicBlockType type_;
// The name of this basic block.
std::string name_;
// The alignment of this basic block.
size_t alignment_;
// The offset of this basic block in the original block. Set to the offset
// of the first byte the basic block originated from during decomposition.
// Useful as a stable, unique identifier for basic blocks in a decomposition.
Offset offset_;
// The set of blocks that reference this basic block. This is exclusive
// of references from other basic blocks, e.g. references from the block
// (or blocks) that are currently decomposed to basic blocks.
BasicBlockReferrerSet referrers_;
// The label associated with this basic block.
BlockGraph::Label label_;
// Tracks whether or not this basic block is unreachable padding.
bool is_padding_;
// The subgraph to which belongs this basic block.
BasicBlockSubGraph* subgraph_;
// The tags that are applied to this object.
TagSet tags_;
private:
DISALLOW_COPY_AND_ASSIGN(BasicBlock);
};
class BasicCodeBlock : public BasicBlock {
public:
// Down-cast from basic block to basic code block.
static BasicCodeBlock* Cast(BasicBlock* basic_block);
static const BasicCodeBlock* Cast(const BasicBlock* basic_block);
// Accessors.
// @{
const Instructions& instructions() const { return instructions_; }
Instructions& instructions() { return instructions_; }
const Successors& successors() const { return successors_; }
Successors& successors() { return successors_; }
// @}
// Returns true iff this basic block is a valid code block - i.e., it
// contains at least one instruction and/or 0-2 successors.
bool IsValid() const override;
// Return the number of bytes required to store the instructions
// this basic block contains, exclusive successors.
Size GetInstructionSize() const;
private:
// BasicBlockSubGraph has a factory for this type.
friend class BasicBlockSubGraph;
// Initialize a basic code block.
// @param subgraph The subgraph to which belongs this basic block.
// @param name A textual identifier for this basic block.
// @param id The unique identifier representing this basic block.
// @note This is protected so that basic-blocks may only be created via the
// subgraph factory.
BasicCodeBlock(BasicBlockSubGraph* subgraph, const base::StringPiece& name,
BlockId id);
// The set of non-branching instructions comprising this basic-block.
// Any branching at the end of the basic-block is represented using the
// successors_ member.
Instructions instructions_;
// The set of (logical) successors to this basic block. There can only be
// 0, 1 or 2 successors in this list.
// If there is a single successor, it must be unconditional.
// If there are two successors, they must have complementary conditions.
Successors successors_;
DISALLOW_COPY_AND_ASSIGN(BasicCodeBlock);
};
class BasicDataBlock : public BasicBlock {
public:
typedef BlockGraph::Block::SourceRange SourceRange;
// Down-cast from basic block to basic data block.
static BasicDataBlock* Cast(BasicBlock* basic_block);
static const BasicDataBlock* Cast(const BasicBlock* basic_block);
// Accessors.
// @{
Size size() const { return size_; }
const uint8_t* data() const { return data_; }
const BasicBlockReferenceMap& references() const { return references_; }
BasicBlockReferenceMap& references() { return references_; }
SourceRange source_range() const { return source_range_; }
void set_source_range(const SourceRange& source_range) {
source_range_ = source_range;
}
const BlockGraph::Label& label() const { return label_; }
void set_label(const BlockGraph::Label& label) { label_ = label; }
bool has_label() const { return label_.IsValid(); }
// @}
// Add a reference @p ref to this basic block at @p offset.
bool SetReference(Offset offset, const BasicBlockReference& ref);
// Returns true iff this basic block is a valid block i.e., it contains data.
bool IsValid() const override;
private:
// BasicBlockSubGraph has a factory for this type.
friend class BasicBlockSubGraph;
// Initialize a basic data or padding block.
// @param subgraph The subgraph to which belongs this basic block.
// @param name A textual identifier for this basic block.
// @param id The unique identifier representing this block.
// @param type The disposition (data or padding) of this basic block.
// @param data The block's data, must be non-NULL.
// @param size The size of @p data, must be greater than zero.
// @note The block does not take ownership of @p data, and @p data must have
// a lifetime greater than the block.
// @note This is protected so that basic-blocks may only be created via the
// subgraph factory.
BasicDataBlock(BasicBlockSubGraph* subgraph,
const base::StringPiece& name,
BlockId id,
const uint8_t* data,
Size size);
// The number of bytes of data in the original block that corresponds with
// this basic block.
Size size_;
// The data in the original block that corresponds with this basic block
// will be referenced here.
const uint8_t* data_;
// The source range, if any, associated with this data block.
SourceRange source_range_;
// The map of references (if any) that this block makes to other basic blocks
// from the original block.
BasicBlockReferenceMap references_;
DISALLOW_COPY_AND_ASSIGN(BasicDataBlock);
};
// A basic end block acts as placeholder block representing beyond the end of
// a block. It acts as a concrete object that allows references and labels to
// be drawn beyond the end of a block, as is often the case with symbol
// information.
class BasicEndBlock : public BasicBlock {
public:
// Down-cast from basic block to basic end block.
static BasicEndBlock* Cast(BasicBlock* basic_block);
static const BasicEndBlock* Cast(const BasicBlock* basic_block);
// Accessors and mutators.
// @{
// An end block always has no size, as it contributes no data to the block.
// It is simply a placeholder for references and labels.
Size size() const { return 0; }
const BasicBlockReferenceMap& references() const { return references_; }
BasicBlockReferenceMap& references() { return references_; }
const BlockGraph::Label& label() const { return label_; }
void set_label(const BlockGraph::Label& label) { label_ = label; }
bool has_label() const { return label_.IsValid(); }
// @}
// Add a reference @p ref to this basic block.
bool SetReference(const BasicBlockReference& ref);
// Returns true iff this basic block is a valid block.
bool IsValid() const override;
private:
// BasicBlockSubGraph has a factory for this type.
friend class BasicBlockSubGraph;
// Initialize a basic data or padding block.
// @param subgraph The subgraph to which belongs this basic block.
// @param id The unique identifier representing this block.
// @note This is protected so that basic-blocks may only be created via the
// subgraph factory.
BasicEndBlock(BasicBlockSubGraph* subgraph,
BlockId id);
// The map of references (if any) that this block makes to other basic blocks
// from the original block.
BasicBlockReferenceMap references_;
DISALLOW_COPY_AND_ASSIGN(BasicEndBlock);
};
// Less-than comparator. Useful to keep ordered set stable.
struct BasicBlockIdLess {
bool operator()(const BasicBlock* lhs,
const BasicBlock* rhs) const {
DCHECK_NE(reinterpret_cast<const BasicBlock*>(NULL), lhs);
DCHECK_NE(reinterpret_cast<const BasicBlock*>(NULL), rhs);
return lhs->id() < rhs->id();
}
};
} // namespace block_graph
#endif // SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_H_