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/IR/LLVMContext.h> 40 #include <llvm/Linker/Linker.h> 41 #include <llvm/Transforms/IPO.h> 42 #include <llvm/Target/TargetMachine.h> 43 #if HAVE_LLVM >= 0x0400 44 #include <llvm/Support/Error.h> 45 #else 46 #include <llvm/Support/ErrorOr.h> 47 #endif 48 49 #if HAVE_LLVM >= 0x0307 50 #include <llvm/IR/LegacyPassManager.h> 51 #include <llvm/Analysis/TargetLibraryInfo.h> 52 #else 53 #include <llvm/PassManager.h> 54 #include <llvm/Target/TargetLibraryInfo.h> 55 #include <llvm/Target/TargetSubtargetInfo.h> 56 #include <llvm/Support/FormattedStream.h> 57 #endif 58 59 #include <clang/Basic/TargetInfo.h> 60 #include <clang/Frontend/CodeGenOptions.h> 61 #include <clang/Frontend/CompilerInstance.h> 62 63 namespace clover { 64 namespace llvm { 65 namespace compat { 66 #if HAVE_LLVM >= 0x0307 67 typedef ::llvm::TargetLibraryInfoImpl target_library_info; 68 #else 69 typedef ::llvm::TargetLibraryInfo target_library_info; 70 #endif 71 72 template<typename T, typename AS> target_address_space(const T & target,const AS lang_as)73 unsigned target_address_space(const T &target, const AS lang_as) { 74 const auto &map = target.getAddressSpaceMap(); 75 #if HAVE_LLVM >= 0x0500 76 return map[static_cast<unsigned>(lang_as)]; 77 #else 78 return map[lang_as - clang::LangAS::Offset]; 79 #endif 80 } 81 82 #if HAVE_LLVM >= 0x0500 83 const clang::InputKind ik_opencl = clang::InputKind::OpenCL; 84 #else 85 const clang::InputKind ik_opencl = clang::IK_OpenCL; 86 #endif 87 88 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)89 set_lang_defaults(clang::CompilerInvocation &inv, 90 clang::LangOptions &lopts, clang::InputKind ik, 91 const ::llvm::Triple &t, 92 clang::PreprocessorOptions &ppopts, 93 clang::LangStandard::Kind std) { 94 #if HAVE_LLVM >= 0x0309 95 inv.setLangDefaults(lopts, ik, t, ppopts, std); 96 #else 97 inv.setLangDefaults(lopts, ik, std); 98 #endif 99 } 100 101 inline void add_link_bitcode_file(clang::CodeGenOptions & opts,const std::string & path)102 add_link_bitcode_file(clang::CodeGenOptions &opts, 103 const std::string &path) { 104 #if HAVE_LLVM >= 0x0500 105 clang::CodeGenOptions::BitcodeFileToLink F; 106 107 F.Filename = path; 108 F.PropagateAttrs = true; 109 F.LinkFlags = ::llvm::Linker::Flags::None; 110 opts.LinkBitcodeFiles.emplace_back(F); 111 #elif HAVE_LLVM >= 0x0308 112 opts.LinkBitcodeFiles.emplace_back(::llvm::Linker::Flags::None, path); 113 #else 114 opts.LinkBitcodeFile = path; 115 #endif 116 } 117 118 #if HAVE_LLVM >= 0x0307 119 typedef ::llvm::legacy::PassManager pass_manager; 120 #else 121 typedef ::llvm::PassManager pass_manager; 122 #endif 123 124 inline void add_data_layout_pass(pass_manager & pm)125 add_data_layout_pass(pass_manager &pm) { 126 #if HAVE_LLVM < 0x0307 127 pm.add(new ::llvm::DataLayoutPass()); 128 #endif 129 } 130 131 inline void add_internalize_pass(pass_manager & pm,const std::vector<std::string> & names)132 add_internalize_pass(pass_manager &pm, 133 const std::vector<std::string> &names) { 134 #if HAVE_LLVM >= 0x0309 135 pm.add(::llvm::createInternalizePass( 136 [=](const ::llvm::GlobalValue &gv) { 137 return std::find(names.begin(), names.end(), 138 gv.getName()) != names.end(); 139 })); 140 #else 141 pm.add(::llvm::createInternalizePass(std::vector<const char *>( 142 map(std::mem_fn(&std::string::data), names)))); 143 #endif 144 } 145 146 inline std::unique_ptr< ::llvm::Linker> create_linker(::llvm::Module & mod)147 create_linker(::llvm::Module &mod) { 148 #if HAVE_LLVM >= 0x0308 149 return std::unique_ptr< ::llvm::Linker>(new ::llvm::Linker(mod)); 150 #else 151 return std::unique_ptr< ::llvm::Linker>(new ::llvm::Linker(&mod)); 152 #endif 153 } 154 155 inline bool link_in_module(::llvm::Linker & linker,std::unique_ptr<::llvm::Module> mod)156 link_in_module(::llvm::Linker &linker, 157 std::unique_ptr< ::llvm::Module> mod) { 158 #if HAVE_LLVM >= 0x0308 159 return linker.linkInModule(std::move(mod)); 160 #else 161 return linker.linkInModule(mod.get()); 162 #endif 163 } 164 165 #if HAVE_LLVM >= 0x0307 166 typedef ::llvm::raw_svector_ostream &raw_ostream_to_emit_file; 167 #else 168 typedef ::llvm::formatted_raw_ostream raw_ostream_to_emit_file; 169 #endif 170 171 #if HAVE_LLVM >= 0x0307 172 typedef ::llvm::DataLayout data_layout; 173 #else 174 typedef const ::llvm::DataLayout *data_layout; 175 #endif 176 177 inline data_layout get_data_layout(::llvm::TargetMachine & tm)178 get_data_layout(::llvm::TargetMachine &tm) { 179 #if HAVE_LLVM >= 0x0307 180 return tm.createDataLayout(); 181 #else 182 return tm.getSubtargetImpl()->getDataLayout(); 183 #endif 184 } 185 186 #if HAVE_LLVM >= 0x0600 187 const auto default_code_model = ::llvm::None; 188 #else 189 const auto default_code_model = ::llvm::CodeModel::Default; 190 #endif 191 192 #if HAVE_LLVM >= 0x0309 193 const auto default_reloc_model = ::llvm::None; 194 #else 195 const auto default_reloc_model = ::llvm::Reloc::Default; 196 #endif 197 198 template<typename M, typename F> void handle_module_error(M & mod,const F & f)199 handle_module_error(M &mod, const F &f) { 200 #if HAVE_LLVM >= 0x0400 201 if (::llvm::Error err = mod.takeError()) 202 ::llvm::handleAllErrors(std::move(err), [&](::llvm::ErrorInfoBase &eib) { 203 f(eib.message()); 204 }); 205 #else 206 if (!mod) 207 f(mod.getError().message()); 208 #endif 209 } 210 211 template<typename T> void set_diagnostic_handler(::llvm::LLVMContext & ctx,T * diagnostic_handler,void * data)212 set_diagnostic_handler(::llvm::LLVMContext &ctx, 213 T *diagnostic_handler, void *data) { 214 #if HAVE_LLVM >= 0x0600 215 ctx.setDiagnosticHandlerCallBack(diagnostic_handler, data); 216 #else 217 ctx.setDiagnosticHandler(diagnostic_handler, data); 218 #endif 219 } 220 } 221 } 222 } 223 224 #endif 225