llvm/bolt/include/bolt/Passes/ValidateInternalCalls.h

//===- bolt/Passes/ValidateInternalCalls.h ----------------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef BOLT_PASSES_VALIDATEINTERNALCALLS_H
#define BOLT_PASSES_VALIDATEINTERNALCALLS_H

#include "bolt/Passes/BinaryPasses.h"

namespace llvm {
namespace bolt {

/// Post-processing for internal calls. What are those? They are call
/// instructions that do not transfer control to another function, but
/// rather branch to a basic block inside the caller function itself.
/// This pass checks that the internal calls observed in a function are
/// manageable. We support two types:
///
///   1. Position Independent Code (PIC) tricks: in this type of internal
///      call, we don't really have a call because the return address is
///      not utilized for branching to, but only as a base address to
///      reference other objects. We call it a "trick" because this is not
///      the standard way a compiler would do this and this will often come
///      from awkwardly written assembly code.
///
///   2. Real internal calls: in this case, a function was inlined inside
///      a caller, but the CALL instruction wasn't removed. This pair of
///      caller-callee is treated as a single function and is analyzed
///      here.
///
/// In general, the rest of the BOLT pipeline (other optimizations, including
/// code reordering) will not support neither of these cases. In this pass,
/// we just identify them, verify they are safe (do not reference objects
/// that will be moved after reordering) and freeze these functions in the
/// way they were read. We do this by marking them as non-simple.
///
/// Why do we freeze them?
///
/// Type 1 is not safe to optimize because any changed offsets will break the
/// PIC references made in this code. Type 2 is not safe to optimize because
/// it requires BOLT to understand a new CFG format where internal calls are
/// broken into two BBs (calling block and returning block), and we currently do
/// not support this  elsewhere. Only this pass is able to make sense of these
/// non-canonical CFGs (specifically, fixBranches does not support them).
///
class ValidateInternalCalls : public BinaryFunctionPass {};

} // namespace bolt
} // namespace llvm

#endif