Home | History | Annotate | Download | only in llvm
      1 //
      2 // Copyright 2016 Francisco Jerez
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a
      5 // copy of this software and associated documentation files (the "Software"),
      6 // to deal in the Software without restriction, including without limitation
      7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 // and/or sell copies of the Software, and to permit persons to whom the
      9 // Software is furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 // OTHER DEALINGS IN THE SOFTWARE.
     21 //
     22 
     23 ///
     24 /// \file
     25 /// Some thin wrappers around the Clang/LLVM API used to preserve
     26 /// compatibility with older API versions while keeping the ifdef clutter low
     27 /// in the rest of the clover::llvm subtree.  In case of an API break please
     28 /// consider whether it's possible to preserve backwards compatibility by
     29 /// introducing a new one-liner inline function or typedef here under the
     30 /// compat namespace in order to keep the running code free from preprocessor
     31 /// conditionals.
     32 ///
     33 
     34 #ifndef CLOVER_LLVM_COMPAT_HPP
     35 #define CLOVER_LLVM_COMPAT_HPP
     36 
     37 #include "util/algorithm.hpp"
     38 
     39 #include <llvm/Linker/Linker.h>
     40 #include <llvm/Transforms/IPO.h>
     41 #include <llvm/Target/TargetMachine.h>
     42 #if HAVE_LLVM >= 0x0400
     43 #include <llvm/Support/Error.h>
     44 #else
     45 #include <llvm/Support/ErrorOr.h>
     46 #endif
     47 
     48 #if HAVE_LLVM >= 0x0307
     49 #include <llvm/IR/LegacyPassManager.h>
     50 #include <llvm/Analysis/TargetLibraryInfo.h>
     51 #else
     52 #include <llvm/PassManager.h>
     53 #include <llvm/Target/TargetLibraryInfo.h>
     54 #include <llvm/Target/TargetSubtargetInfo.h>
     55 #include <llvm/Support/FormattedStream.h>
     56 #endif
     57 
     58 #include <clang/Frontend/CodeGenOptions.h>
     59 #include <clang/Frontend/CompilerInstance.h>
     60 
     61 namespace clover {
     62    namespace llvm {
     63       namespace compat {
     64 #if HAVE_LLVM >= 0x0307
     65          typedef ::llvm::TargetLibraryInfoImpl target_library_info;
     66 #else
     67          typedef ::llvm::TargetLibraryInfo target_library_info;
     68 #endif
     69 
     70          inline void
     71          set_lang_defaults(clang::CompilerInvocation &inv,
     72                            clang::LangOptions &lopts, clang::InputKind ik,
     73                            const ::llvm::Triple &t,
     74                            clang::PreprocessorOptions &ppopts,
     75                            clang::LangStandard::Kind std) {
     76 #if HAVE_LLVM >= 0x0309
     77             inv.setLangDefaults(lopts, ik, t, ppopts, std);
     78 #else
     79             inv.setLangDefaults(lopts, ik, std);
     80 #endif
     81          }
     82 
     83          inline void
     84          add_link_bitcode_file(clang::CodeGenOptions &opts,
     85                                const std::string &path) {
     86 #if HAVE_LLVM >= 0x0308
     87             opts.LinkBitcodeFiles.emplace_back(::llvm::Linker::Flags::None, path);
     88 #else
     89             opts.LinkBitcodeFile = path;
     90 #endif
     91          }
     92 
     93 #if HAVE_LLVM >= 0x0307
     94          typedef ::llvm::legacy::PassManager pass_manager;
     95 #else
     96          typedef ::llvm::PassManager pass_manager;
     97 #endif
     98 
     99          inline void
    100          add_data_layout_pass(pass_manager &pm) {
    101 #if HAVE_LLVM < 0x0307
    102             pm.add(new ::llvm::DataLayoutPass());
    103 #endif
    104          }
    105 
    106          inline void
    107          add_internalize_pass(pass_manager &pm,
    108                               const std::vector<std::string> &names) {
    109 #if HAVE_LLVM >= 0x0309
    110             pm.add(::llvm::createInternalizePass(
    111                       [=](const ::llvm::GlobalValue &gv) {
    112                          return std::find(names.begin(), names.end(),
    113                                           gv.getName()) != names.end();
    114                       }));
    115 #else
    116             pm.add(::llvm::createInternalizePass(std::vector<const char *>(
    117                       map(std::mem_fn(&std::string::data), names))));
    118 #endif
    119          }
    120 
    121          inline std::unique_ptr<::llvm::Linker>
    122          create_linker(::llvm::Module &mod) {
    123 #if HAVE_LLVM >= 0x0308
    124             return std::unique_ptr<::llvm::Linker>(new ::llvm::Linker(mod));
    125 #else
    126             return std::unique_ptr<::llvm::Linker>(new ::llvm::Linker(&mod));
    127 #endif
    128          }
    129 
    130          inline bool
    131          link_in_module(::llvm::Linker &linker,
    132                         std::unique_ptr<::llvm::Module> mod) {
    133 #if HAVE_LLVM >= 0x0308
    134             return linker.linkInModule(std::move(mod));
    135 #else
    136             return linker.linkInModule(mod.get());
    137 #endif
    138          }
    139 
    140 #if HAVE_LLVM >= 0x0307
    141          typedef ::llvm::raw_svector_ostream &raw_ostream_to_emit_file;
    142 #else
    143          typedef ::llvm::formatted_raw_ostream raw_ostream_to_emit_file;
    144 #endif
    145 
    146 #if HAVE_LLVM >= 0x0307
    147          typedef ::llvm::DataLayout data_layout;
    148 #else
    149          typedef const ::llvm::DataLayout *data_layout;
    150 #endif
    151 
    152          inline data_layout
    153          get_data_layout(::llvm::TargetMachine &tm) {
    154 #if HAVE_LLVM >= 0x0307
    155             return tm.createDataLayout();
    156 #else
    157             return tm.getSubtargetImpl()->getDataLayout();
    158 #endif
    159          }
    160 
    161 #if HAVE_LLVM >= 0x0309
    162          const auto default_reloc_model = ::llvm::None;
    163 #else
    164          const auto default_reloc_model = ::llvm::Reloc::Default;
    165 #endif
    166 
    167          template<typename M, typename F> void
    168          handle_module_error(M &mod, const F &f) {
    169 #if HAVE_LLVM >= 0x0400
    170             if (::llvm::Error err = mod.takeError())
    171                ::llvm::handleAllErrors(std::move(err), [&](::llvm::ErrorInfoBase &eib) {
    172                      f(eib.message());
    173                   });
    174 #else
    175             if (!mod)
    176                f(mod.getError().message());
    177 #endif
    178          }
    179       }
    180    }
    181 }
    182 
    183 #endif
    184