18195637363c9a5d979831405390157b11ecfc170Francisco Jerez// 28195637363c9a5d979831405390157b11ecfc170Francisco Jerez// Copyright 2012-2016 Francisco Jerez 38195637363c9a5d979831405390157b11ecfc170Francisco Jerez// Copyright 2012-2016 Advanced Micro Devices, Inc. 48195637363c9a5d979831405390157b11ecfc170Francisco Jerez// 58195637363c9a5d979831405390157b11ecfc170Francisco Jerez// Permission is hereby granted, free of charge, to any person obtaining a 68195637363c9a5d979831405390157b11ecfc170Francisco Jerez// copy of this software and associated documentation files (the "Software"), 78195637363c9a5d979831405390157b11ecfc170Francisco Jerez// to deal in the Software without restriction, including without limitation 88195637363c9a5d979831405390157b11ecfc170Francisco Jerez// the rights to use, copy, modify, merge, publish, distribute, sublicense, 98195637363c9a5d979831405390157b11ecfc170Francisco Jerez// and/or sell copies of the Software, and to permit persons to whom the 108195637363c9a5d979831405390157b11ecfc170Francisco Jerez// Software is furnished to do so, subject to the following conditions: 118195637363c9a5d979831405390157b11ecfc170Francisco Jerez// 128195637363c9a5d979831405390157b11ecfc170Francisco Jerez// The above copyright notice and this permission notice shall be included in 138195637363c9a5d979831405390157b11ecfc170Francisco Jerez// all copies or substantial portions of the Software. 148195637363c9a5d979831405390157b11ecfc170Francisco Jerez// 158195637363c9a5d979831405390157b11ecfc170Francisco Jerez// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168195637363c9a5d979831405390157b11ecfc170Francisco Jerez// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178195637363c9a5d979831405390157b11ecfc170Francisco Jerez// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188195637363c9a5d979831405390157b11ecfc170Francisco Jerez// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 198195637363c9a5d979831405390157b11ecfc170Francisco Jerez// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 208195637363c9a5d979831405390157b11ecfc170Francisco Jerez// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 218195637363c9a5d979831405390157b11ecfc170Francisco Jerez// OTHER DEALINGS IN THE SOFTWARE. 228195637363c9a5d979831405390157b11ecfc170Francisco Jerez// 238195637363c9a5d979831405390157b11ecfc170Francisco Jerez 248195637363c9a5d979831405390157b11ecfc170Francisco Jerez/// 258195637363c9a5d979831405390157b11ecfc170Francisco Jerez/// \file 268195637363c9a5d979831405390157b11ecfc170Francisco Jerez/// Trivial codegen back-end that simply passes through the existing LLVM IR 271a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez/// and either formats it so it can be consumed by pipe drivers (if 281a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez/// build_module_bitcode() is used) or serializes so it can be deserialized at 291a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez/// a later point and passed to the actual codegen back-end (if 301a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez/// build_module_library() / parse_module_library() is used), potentially 311a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez/// after linking against other bitcode object files. 328195637363c9a5d979831405390157b11ecfc170Francisco Jerez/// 338195637363c9a5d979831405390157b11ecfc170Francisco Jerez 348195637363c9a5d979831405390157b11ecfc170Francisco Jerez#include "llvm/codegen.hpp" 3595ddb37708ca16ccbd0f607d17a82be2de0d07b6Vedran Miletić#include "llvm/compat.hpp" 368195637363c9a5d979831405390157b11ecfc170Francisco Jerez#include "llvm/metadata.hpp" 378195637363c9a5d979831405390157b11ecfc170Francisco Jerez#include "core/error.hpp" 388195637363c9a5d979831405390157b11ecfc170Francisco Jerez#include "util/algorithm.hpp" 398195637363c9a5d979831405390157b11ecfc170Francisco Jerez 408195637363c9a5d979831405390157b11ecfc170Francisco Jerez#include <map> 413ff9f8c5328310a463d3f16f573b68aa20ab8339Laurent Carlier#if HAVE_LLVM < 0x0400 428195637363c9a5d979831405390157b11ecfc170Francisco Jerez#include <llvm/Bitcode/ReaderWriter.h> 433ff9f8c5328310a463d3f16f573b68aa20ab8339Laurent Carlier#else 443ff9f8c5328310a463d3f16f573b68aa20ab8339Laurent Carlier#include <llvm/Bitcode/BitcodeReader.h> 453ff9f8c5328310a463d3f16f573b68aa20ab8339Laurent Carlier#include <llvm/Bitcode/BitcodeWriter.h> 463ff9f8c5328310a463d3f16f573b68aa20ab8339Laurent Carlier#endif 478195637363c9a5d979831405390157b11ecfc170Francisco Jerez#include <llvm/Support/raw_ostream.h> 488195637363c9a5d979831405390157b11ecfc170Francisco Jerez 498195637363c9a5d979831405390157b11ecfc170Francisco Jerezusing namespace clover; 508195637363c9a5d979831405390157b11ecfc170Francisco Jerezusing namespace clover::llvm; 518195637363c9a5d979831405390157b11ecfc170Francisco Jerez 528195637363c9a5d979831405390157b11ecfc170Francisco Jereznamespace { 538195637363c9a5d979831405390157b11ecfc170Francisco Jerez std::map<std::string, unsigned> 548195637363c9a5d979831405390157b11ecfc170Francisco Jerez get_symbol_offsets(const ::llvm::Module &mod) { 558195637363c9a5d979831405390157b11ecfc170Francisco Jerez std::map<std::string, unsigned> offsets; 568195637363c9a5d979831405390157b11ecfc170Francisco Jerez unsigned i = 0; 578195637363c9a5d979831405390157b11ecfc170Francisco Jerez 588195637363c9a5d979831405390157b11ecfc170Francisco Jerez for (const auto &name : map(std::mem_fn(&::llvm::Function::getName), 598195637363c9a5d979831405390157b11ecfc170Francisco Jerez get_kernels(mod))) 608195637363c9a5d979831405390157b11ecfc170Francisco Jerez offsets[name] = i++; 618195637363c9a5d979831405390157b11ecfc170Francisco Jerez 628195637363c9a5d979831405390157b11ecfc170Francisco Jerez return offsets; 638195637363c9a5d979831405390157b11ecfc170Francisco Jerez } 648195637363c9a5d979831405390157b11ecfc170Francisco Jerez 658195637363c9a5d979831405390157b11ecfc170Francisco Jerez std::vector<char> 668195637363c9a5d979831405390157b11ecfc170Francisco Jerez emit_code(const ::llvm::Module &mod) { 678195637363c9a5d979831405390157b11ecfc170Francisco Jerez ::llvm::SmallVector<char, 1024> data; 688195637363c9a5d979831405390157b11ecfc170Francisco Jerez ::llvm::raw_svector_ostream os { data }; 698195637363c9a5d979831405390157b11ecfc170Francisco Jerez WriteBitcodeToFile(&mod, os); 708195637363c9a5d979831405390157b11ecfc170Francisco Jerez return { os.str().begin(), os.str().end() }; 718195637363c9a5d979831405390157b11ecfc170Francisco Jerez } 728195637363c9a5d979831405390157b11ecfc170Francisco Jerez} 738195637363c9a5d979831405390157b11ecfc170Francisco Jerez 748195637363c9a5d979831405390157b11ecfc170Francisco Jerezmodule 758195637363c9a5d979831405390157b11ecfc170Francisco Jerezclover::llvm::build_module_bitcode(const ::llvm::Module &mod, 768195637363c9a5d979831405390157b11ecfc170Francisco Jerez const clang::CompilerInstance &c) { 778195637363c9a5d979831405390157b11ecfc170Francisco Jerez return build_module_common(mod, emit_code(mod), get_symbol_offsets(mod), c); 788195637363c9a5d979831405390157b11ecfc170Francisco Jerez} 798195637363c9a5d979831405390157b11ecfc170Francisco Jerez 808195637363c9a5d979831405390157b11ecfc170Francisco Jerezstd::string 818195637363c9a5d979831405390157b11ecfc170Francisco Jerezclover::llvm::print_module_bitcode(const ::llvm::Module &mod) { 828195637363c9a5d979831405390157b11ecfc170Francisco Jerez std::string s; 838195637363c9a5d979831405390157b11ecfc170Francisco Jerez ::llvm::raw_string_ostream os { s }; 848195637363c9a5d979831405390157b11ecfc170Francisco Jerez mod.print(os, NULL); 858195637363c9a5d979831405390157b11ecfc170Francisco Jerez return os.str(); 868195637363c9a5d979831405390157b11ecfc170Francisco Jerez} 871a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez 881a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerezmodule 89cc495055cdfe7e39002180d095d09fe4b6905eb9Serge Martinclover::llvm::build_module_library(const ::llvm::Module &mod, 90cc495055cdfe7e39002180d095d09fe4b6905eb9Serge Martin enum module::section::type section_type) { 911a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez module m; 921a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez const auto code = emit_code(mod); 93cc495055cdfe7e39002180d095d09fe4b6905eb9Serge Martin m.secs.emplace_back(0, section_type, code.size(), code); 941a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez return m; 951a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez} 961a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez 971a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerezstd::unique_ptr<::llvm::Module> 981a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerezclover::llvm::parse_module_library(const module &m, ::llvm::LLVMContext &ctx, 991a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez std::string &r_log) { 1001a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez auto mod = ::llvm::parseBitcodeFile(::llvm::MemoryBufferRef( 1011a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez as_string(m.secs[0].data), " "), ctx); 1028e430ff8b060b4e8e922bae24b3c57837da6ea77Vedran Miletić 10395ddb37708ca16ccbd0f607d17a82be2de0d07b6Vedran Miletić compat::handle_module_error(mod, [&](const std::string &s) { 10495ddb37708ca16ccbd0f607d17a82be2de0d07b6Vedran Miletić fail(r_log, error(CL_INVALID_PROGRAM), s); 1058e430ff8b060b4e8e922bae24b3c57837da6ea77Vedran Miletić }); 1061a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez 1071a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez return std::unique_ptr<::llvm::Module>(std::move(*mod)); 1081a7d11aa3dc65e89f0d801707951afc32cbaa6eeFrancisco Jerez} 109