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 set_lang_defaults(clang::CompilerInvocation & inv,clang::LangOptions & lopts,clang::InputKind ik,const::llvm::Triple & t,clang::PreprocessorOptions & ppopts,clang::LangStandard::Kind std)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 add_link_bitcode_file(clang::CodeGenOptions & opts,const std::string & path)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 add_data_layout_pass(pass_manager & pm)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 add_internalize_pass(pass_manager & pm,const std::vector<std::string> & names)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> create_linker(::llvm::Module & mod)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 link_in_module(::llvm::Linker & linker,std::unique_ptr<::llvm::Module> mod)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 get_data_layout(::llvm::TargetMachine & tm)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 handle_module_error(M & mod,const F & f)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