llvm-project/lld/lib/ReaderWriter/ELF/CreateELF.h

110 lines
4.0 KiB
C++

//===- lib/ReaderWriter/ELF/CreateELF.h -----------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file provides a simple way to create an object templated on
/// ELFType depending on the runtime type needed.
///
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_CREATE_ELF_H
#define LLD_READER_WRITER_ELF_CREATE_ELF_H
#include "llvm/Object/ELF.h"
#include "llvm/Support/Compiler.h"
namespace {
using llvm::object::ELFType;
/// \func createELF
/// \brief Create an object depending on the runtime attributes and alignment
/// of an ELF file.
///
/// \param Traits
/// Traits::result_type must be a type convertable from what create returns.
/// Traits::create must be a template function which takes an ELFType and
/// returns something convertable to Traits::result_type.
///
/// \param ident pair of EI_CLASS and EI_DATA.
/// \param maxAlignment the maximum alignment of the file.
/// \param args arguments forwarded to CreateELFTraits<T>::create.
#define LLVM_CREATE_ELF_CreateELFTraits(endian, align, is64, ...) \
Traits::template create<ELFType<llvm::support::endian, align, is64>>( \
__VA_ARGS__);
#if !LLVM_IS_UNALIGNED_ACCESS_FAST
# define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \
if (maxAlignment >= normal) \
return LLVM_CREATE_ELF_CreateELFTraits(endian, normal, is64, __VA_ARGS__) \
else if (maxAlignment >= low) \
return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \
else \
llvm_unreachable("Invalid alignment for ELF file!");
#else
# define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \
if (maxAlignment >= low) \
return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \
else \
llvm_unreachable("Invalid alignment for ELF file!");
#endif
#define LLVM_CREATE_ELF_IMPL(...) \
if (ident.first == llvm::ELF::ELFCLASS32 && \
ident.second == llvm::ELF::ELFDATA2LSB) { \
LLVM_CREATE_ELF_MaxAlignCheck(4, 2, little, false, __VA_ARGS__) \
} else if (ident.first == llvm::ELF::ELFCLASS32 && \
ident.second == llvm::ELF::ELFDATA2MSB) { \
LLVM_CREATE_ELF_MaxAlignCheck(4, 2, big, false, __VA_ARGS__) \
} else if (ident.first == llvm::ELF::ELFCLASS64 && \
ident.second == llvm::ELF::ELFDATA2MSB) { \
LLVM_CREATE_ELF_MaxAlignCheck(8, 2, big, true, __VA_ARGS__) \
} else if (ident.first == llvm::ELF::ELFCLASS64 && \
ident.second == llvm::ELF::ELFDATA2LSB) { \
LLVM_CREATE_ELF_MaxAlignCheck(8, 2, little, true, __VA_ARGS__) \
} \
llvm_unreachable("Invalid ELF type!");
#if LLVM_HAS_VARIADIC_TEMPLATES
template <class Traits, class ...Args>
typename Traits::result_type createELF(
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
Args &&...args) {
LLVM_CREATE_ELF_IMPL(std::forward<Args>(args)...)
}
#else
template <class Traits, class T1>
typename Traits::result_type createELF(
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
T1 &&t1) {
LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1))
}
template <class Traits, class T1, class T2>
typename Traits::result_type createELF(
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
T1 &&t1, T2 &&t2) {
LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2))
}
template <class Traits, class T1, class T2, class T3>
typename Traits::result_type createELF(
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
T1 &&t1, T2 &&t2, T3 &&t3) {
LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2),
std::forward<T3>(t3))
}
#endif // LLVM_HAS_VARIADIC_TEMPLATES
} // end anon namespace
#undef LLVM_CREATE_ELF_CreateELFTraits
#undef LLVM_CREATE_ELF_MaxAlignCheck
#undef LLVM_CREATE_ELF_IMPL
#endif