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