1//
2// Copyright 2012-2016 Francisco Jerez
3// Copyright 2012-2016 Advanced Micro Devices, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21// OTHER DEALINGS IN THE SOFTWARE.
22//
23
24///
25/// \file
26/// Trivial codegen back-end that simply passes through the existing LLVM IR
27/// and either formats it so it can be consumed by pipe drivers (if
28/// build_module_bitcode() is used) or serializes so it can be deserialized at
29/// a later point and passed to the actual codegen back-end (if
30/// build_module_library() / parse_module_library() is used), potentially
31/// after linking against other bitcode object files.
32///
33
34#include "llvm/codegen.hpp"
35#include "llvm/compat.hpp"
36#include "llvm/metadata.hpp"
37#include "core/error.hpp"
38#include "util/algorithm.hpp"
39
40#include <map>
41#if HAVE_LLVM < 0x0400
42#include <llvm/Bitcode/ReaderWriter.h>
43#else
44#include <llvm/Bitcode/BitcodeReader.h>
45#include <llvm/Bitcode/BitcodeWriter.h>
46#endif
47#include <llvm/Support/raw_ostream.h>
48
49using namespace clover;
50using namespace clover::llvm;
51
52namespace {
53   std::map<std::string, unsigned>
54   get_symbol_offsets(const ::llvm::Module &mod) {
55      std::map<std::string, unsigned> offsets;
56      unsigned i = 0;
57
58      for (const auto &name : map(std::mem_fn(&::llvm::Function::getName),
59                                  get_kernels(mod)))
60         offsets[name] = i++;
61
62      return offsets;
63   }
64
65   std::vector<char>
66   emit_code(const ::llvm::Module &mod) {
67      ::llvm::SmallVector<char, 1024> data;
68      ::llvm::raw_svector_ostream os { data };
69      WriteBitcodeToFile(&mod, os);
70      return { os.str().begin(), os.str().end() };
71   }
72}
73
74module
75clover::llvm::build_module_bitcode(const ::llvm::Module &mod,
76                                   const clang::CompilerInstance &c) {
77   return build_module_common(mod, emit_code(mod), get_symbol_offsets(mod), c);
78}
79
80std::string
81clover::llvm::print_module_bitcode(const ::llvm::Module &mod) {
82   std::string s;
83   ::llvm::raw_string_ostream os { s };
84   mod.print(os, NULL);
85   return os.str();
86}
87
88module
89clover::llvm::build_module_library(const ::llvm::Module &mod,
90                                   enum module::section::type section_type) {
91   module m;
92   const auto code = emit_code(mod);
93   m.secs.emplace_back(0, section_type, code.size(), code);
94   return m;
95}
96
97std::unique_ptr<::llvm::Module>
98clover::llvm::parse_module_library(const module &m, ::llvm::LLVMContext &ctx,
99                                   std::string &r_log) {
100   auto mod = ::llvm::parseBitcodeFile(::llvm::MemoryBufferRef(
101                                        as_string(m.secs[0].data), " "), ctx);
102
103   compat::handle_module_error(mod, [&](const std::string &s) {
104         fail(r_log, error(CL_INVALID_PROGRAM), s);
105      });
106
107   return std::unique_ptr<::llvm::Module>(std::move(*mod));
108}
109