diff options
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/CreateELF.h')
-rw-r--r-- | lld/lib/ReaderWriter/ELF/CreateELF.h | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/ELF/CreateELF.h b/lld/lib/ReaderWriter/ELF/CreateELF.h new file mode 100644 index 00000000000..8a29976438a --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/CreateELF.h @@ -0,0 +1,109 @@ +//===- 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 |