summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/CreateELF.h
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/CreateELF.h')
-rw-r--r--lld/lib/ReaderWriter/ELF/CreateELF.h109
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
OpenPOWER on IntegriCloud