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