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#if HAVE_LLVM < 0x0400 40#include <llvm/Bitcode/ReaderWriter.h> 41#else 42#include <llvm/Bitcode/BitcodeReader.h> 43#include <llvm/Bitcode/BitcodeWriter.h> 44#endif 45 46#include <llvm/IR/LLVMContext.h> 47#include <llvm/Linker/Linker.h> 48#include <llvm/Transforms/IPO.h> 49#include <llvm/Transforms/Utils/Cloning.h> 50#include <llvm/Target/TargetMachine.h> 51#if HAVE_LLVM >= 0x0400 52#include <llvm/Support/Error.h> 53#else 54#include <llvm/Support/ErrorOr.h> 55#endif 56 57#include <llvm/IR/LegacyPassManager.h> 58#include <llvm/Analysis/TargetLibraryInfo.h> 59 60#include <clang/Basic/TargetInfo.h> 61#include <clang/Frontend/CompilerInstance.h> 62 63#if HAVE_LLVM >= 0x0800 64#include <clang/Basic/CodeGenOptions.h> 65#else 66#include <clang/Frontend/CodeGenOptions.h> 67#endif 68 69namespace clover { 70 namespace llvm { 71 namespace compat { 72 template<typename T, typename 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 const clang::LangStandard::Kind lang_opencl10 = clang::LangStandard::lang_opencl10; 85#else 86 const clang::InputKind ik_opencl = clang::IK_OpenCL; 87 const clang::LangStandard::Kind lang_opencl10 = clang::LangStandard::lang_opencl; 88#endif 89 90 inline void 91 add_link_bitcode_file(clang::CodeGenOptions &opts, 92 const std::string &path) { 93#if HAVE_LLVM >= 0x0500 94 clang::CodeGenOptions::BitcodeFileToLink F; 95 96 F.Filename = path; 97 F.PropagateAttrs = true; 98 F.LinkFlags = ::llvm::Linker::Flags::None; 99 opts.LinkBitcodeFiles.emplace_back(F); 100#else 101 opts.LinkBitcodeFiles.emplace_back(::llvm::Linker::Flags::None, path); 102#endif 103 } 104 105#if HAVE_LLVM >= 0x0600 106 const auto default_code_model = ::llvm::None; 107#else 108 const auto default_code_model = ::llvm::CodeModel::Default; 109#endif 110 111 template<typename M, typename F> void 112 handle_module_error(M &mod, const F &f) { 113#if HAVE_LLVM >= 0x0400 114 if (::llvm::Error err = mod.takeError()) 115 ::llvm::handleAllErrors(std::move(err), [&](::llvm::ErrorInfoBase &eib) { 116 f(eib.message()); 117 }); 118#else 119 if (!mod) 120 f(mod.getError().message()); 121#endif 122 } 123 124 template<typename T> void 125 set_diagnostic_handler(::llvm::LLVMContext &ctx, 126 T *diagnostic_handler, void *data) { 127#if HAVE_LLVM >= 0x0600 128 ctx.setDiagnosticHandlerCallBack(diagnostic_handler, data); 129#else 130 ctx.setDiagnosticHandler(diagnostic_handler, data); 131#endif 132 } 133 134 inline std::unique_ptr< ::llvm::Module> 135 clone_module(const ::llvm::Module &mod) 136 { 137#if HAVE_LLVM >= 0x0700 138 return ::llvm::CloneModule(mod); 139#else 140 return ::llvm::CloneModule(&mod); 141#endif 142 } 143 144 template<typename T> void 145 write_bitcode_to_file(const ::llvm::Module &mod, T &os) 146 { 147#if HAVE_LLVM >= 0x0700 148 ::llvm::WriteBitcodeToFile(mod, os); 149#else 150 ::llvm::WriteBitcodeToFile(&mod, os); 151#endif 152 } 153 154 template<typename TM, typename PM, typename OS, typename FT> 155 bool add_passes_to_emit_file(TM &tm, PM &pm, OS &os, FT &ft) 156 { 157#if HAVE_LLVM >= 0x0700 158 return tm.addPassesToEmitFile(pm, os, nullptr, ft); 159#else 160 return tm.addPassesToEmitFile(pm, os, ft); 161#endif 162 } 163 164 template<typename T, typename M> 165 T get_abi_type(const T &arg_type, const M &mod) { 166#if HAVE_LLVM >= 0x0700 167 return arg_type; 168#else 169 ::llvm::DataLayout dl(&mod); 170 const unsigned arg_store_size = dl.getTypeStoreSize(arg_type); 171 return !arg_type->isIntegerTy() ? arg_type : 172 dl.getSmallestLegalIntType(mod.getContext(), arg_store_size * 8); 173#endif 174 } 175 } 176 } 177} 178 179#endif 180