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 61namespace 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