summary refs log tree commit diff
path: root/src/rustllvm/RustWrapper.cpp
blob: eb06398c48e642d2714a77af7ca4b22e63dfe3ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//===- RustWrapper.cpp - Rust wrapper for core functions --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines alternate interfaces to core functions that are more
// readily callable by Rust's FFI.
//
//===----------------------------------------------------------------------===//

#include "llvm/Linker.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Host.h"
#include "llvm-c/Core.h"
#include "llvm-c/BitReader.h"
#include "llvm-c/Object.h"
#include <cstdlib>

using namespace llvm;

static const char *LLVMRustError;

extern "C" LLVMMemoryBufferRef
LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
  LLVMMemoryBufferRef MemBuf = NULL;
  LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf,
    const_cast<char **>(&LLVMRustError));
  return MemBuf;
}

extern "C" const char *LLVMRustGetLastError(void) {
  return LLVMRustError;
}

extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM);
extern "C" void LLVMAddStandardModulePasses(LLVMPassManagerRef PM,
    unsigned int OptimizationLevel, bool OptimizeSize, bool UnitAtATime,
    bool UnrollLoops, bool SimplifyLibCalls,
    unsigned int InliningThreshold);

int *RustHackToFetchPassesO = (int*)LLVMAddBasicAliasAnalysisPass;
int *RustHackToFetchPasses2O = (int*)LLVMAddStandardModulePasses;

enum LLVMCodeGenFileType {
  LLVMAssemblyFile,
  LLVMObjectFile,
  LLVMNullFile         // Do not emit any output.
};

extern "C" bool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src) {
  static std::string err;

  // For some strange reason, unwrap() doesn't work here. "No matching
  // function" error.
  Module *DM = reinterpret_cast<Module *>(Dest);
  Module *SM = reinterpret_cast<Module *>(Src);
  if (Linker::LinkModules(DM, SM, &err)) {
    LLVMRustError = err.c_str();
    return false;
  }
  return true;
}

extern "C" void LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
                                        LLVMModuleRef M,
                                        const char *triple,
                                        const char *path,
                                        LLVMCodeGenFileType FileType) {

  // Set compilation options.
  llvm::NoFramePointerElim = true;

  InitializeAllTargets();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();
  TargetMachine::setRelocationModel(Reloc::PIC_);
  std::string Err;
  const Target *TheTarget = TargetRegistry::lookupTarget(triple, Err);
  std::string FeaturesStr;
  TargetMachine *Target = TheTarget->createTargetMachine(triple, FeaturesStr);
  bool NoVerify = false;
  CodeGenOpt::Level OLvl = CodeGenOpt::Default;
  PassManager *PM = unwrap<PassManager>(PMR);
  std::string ErrorInfo;
  raw_fd_ostream OS(path, ErrorInfo,
                    raw_fd_ostream::F_Binary);
  formatted_raw_ostream FOS(OS);
  TargetMachine::CodeGenFileType FileType2 =
    static_cast<TargetMachine::CodeGenFileType>(FileType);

  bool foo = Target->addPassesToEmitFile(*PM, FOS, FileType2, OLvl, NoVerify);
  assert(!foo);
  (void)foo;
  PM->run(*unwrap(M));
  delete Target;
}

extern "C" LLVMModuleRef LLVMRustParseBitcode(LLVMMemoryBufferRef MemBuf) {
  LLVMModuleRef M;
  return LLVMParseBitcode(MemBuf, &M, const_cast<char **>(&LLVMRustError))
         ? NULL : M;
}

extern "C" const char *LLVMRustGetHostTriple(void)
{
  static std::string str = llvm::sys::getHostTriple();
  return str.c_str();
}

extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N,
                                              LLVMBool SignExtend) {
  return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend);
}

extern bool llvm::TimePassesIsEnabled;
extern "C" void LLVMRustEnableTimePasses() {
  TimePassesIsEnabled = true;
}

extern "C" void LLVMRustPrintPassTimings() {
  raw_fd_ostream OS (2, false); // stderr.
  TimerGroup::printAll(OS);
}