blob: 2f85232591d951a5b54ab5cd7f1f1116f46ba1ed [file] [log] [blame]
//===- bolt/Core/JumpTable.h - Jump table at low-level IR -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the JumpTable class, which represents a jump table in a
// binary file.
//
//===----------------------------------------------------------------------===//
#ifndef BOLT_CORE_JUMP_TABLE_H
#define BOLT_CORE_JUMP_TABLE_H
#include "bolt/Core/BinaryData.h"
#include <map>
#include <vector>
namespace llvm {
class MCSymbol;
class raw_ostream;
namespace bolt {
enum JumpTableSupportLevel : char {
JTS_NONE = 0, /// Disable jump tables support.
JTS_BASIC = 1, /// Enable basic jump tables support (in-place).
JTS_MOVE = 2, /// Move jump tables to a separate section.
JTS_SPLIT = 3, /// Enable hot/cold splitting of jump tables.
JTS_AGGRESSIVE = 4, /// Aggressive splitting of jump tables.
};
class BinaryFunction;
/// Representation of a jump table.
///
/// The jump table may include other jump tables that are referenced by
/// a different label at a different offset in this jump table.
class JumpTable : public BinaryData {
friend class BinaryContext;
JumpTable() = delete;
JumpTable(const JumpTable &) = delete;
JumpTable &operator=(const JumpTable &) = delete;
public:
enum JumpTableType : char {
JTT_NORMAL,
JTT_PIC,
};
/// Branch statistics for jump table entries.
struct JumpInfo {
uint64_t Mispreds{0};
uint64_t Count{0};
};
/// Size of the entry used for storage.
size_t EntrySize;
/// Size of the entry size we will write (we may use a more compact layout)
size_t OutputEntrySize;
/// The type of this jump table.
JumpTableType Type;
/// All the entries as labels.
std::vector<MCSymbol *> Entries;
/// All the entries as absolute addresses. Invalid after disassembly is done.
using AddressesType = std::vector<uint64_t>;
AddressesType EntriesAsAddress;
/// Map <Offset> -> <Label> used for embedded jump tables. Label at 0 offset
/// is the main label for the jump table.
using LabelMapType = std::map<unsigned, MCSymbol *>;
LabelMapType Labels;
/// Dynamic number of times each entry in the table was referenced.
/// Identical entries will have a shared count (identical for every
/// entry in the set).
std::vector<JumpInfo> Counts;
/// Total number of times this jump table was used.
uint64_t Count{0};
/// BinaryFunction this jump tables belongs to.
SmallVector<BinaryFunction *, 1> Parents;
private:
/// Constructor should only be called by a BinaryContext.
JumpTable(MCSymbol &Symbol, uint64_t Address, size_t EntrySize,
JumpTableType Type, LabelMapType &&Labels, BinarySection &Section);
public:
/// Return the size of the jump table.
uint64_t getSize() const {
return std::max(EntriesAsAddress.size(), Entries.size()) * EntrySize;
}
const MCSymbol *getFirstLabel() const {
assert(Labels.count(0) != 0 && "labels must have an entry at 0");
return Labels.find(0)->second;
}
/// Get the indexes for symbol entries that correspond to the jump table
/// starting at (or containing) 'Addr'.
std::pair<size_t, size_t> getEntriesForAddress(const uint64_t Addr) const;
bool isJumpTable() const override { return true; }
/// Change all entries of the jump table in \p JTAddress pointing to
/// \p OldDest to \p NewDest. Return false if unsuccessful.
bool replaceDestination(uint64_t JTAddress, const MCSymbol *OldDest,
MCSymbol *NewDest);
/// Update jump table at its original location.
void updateOriginal();
/// Print for debugging purposes.
void print(raw_ostream &OS) const override;
};
} // namespace bolt
} // namespace llvm
#endif