summaryrefslogtreecommitdiff
path: root/tools/lli/lli.cpp
blob: 82b354dc18a516879ba085a4255c7201720d9068 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This utility provides a way to execute LLVM bytecode without static
// compilation.  This consists of a very simple and slow (but portable)
// interpreter, along with capability for system specific dynamic compilers.  At
// runtime, the fastest (stable) execution engine is selected to run the
// program.  This means the JIT compiler for the current platform if it's
// available.
//
//===----------------------------------------------------------------------===//

#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
#include "Support/Debug.h"
#include "Support/SystemUtils.h"

using namespace llvm;

namespace {
  cl::opt<std::string>
  InputFile(cl::desc("<input bytecode>"), cl::Positional, cl::init("-"));

  cl::list<std::string>
  InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>..."));

  cl::opt<std::string>
  MainFunction("f", cl::desc("Function to execute"), cl::init("main"),
               cl::value_desc("function name"));

  cl::opt<bool> ForceInterpreter("force-interpreter",
                                 cl::desc("Force interpretation: disable JIT"),
                                 cl::init(false));

  cl::opt<std::string>
  FakeArgv0("fake-argv0",
            cl::desc("Override the 'argv[0]' value passed into the executing"
                     " program"), cl::value_desc("executable"));
}

static std::vector<std::string> makeStringVector(char * const *envp) {
  std::vector<std::string> rv;
  for (unsigned i = 0; envp[i]; ++i)
    rv.push_back(envp[i]);
  return rv;
}

static void *CreateArgv(ExecutionEngine *EE,
                        const std::vector<std::string> &InputArgv) {
  if (EE->getTargetData().getPointerSize() == 8) {   // 64 bit target?
    PointerTy *Result = new PointerTy[InputArgv.size()+1];
    DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");

    for (unsigned i = 0; i < InputArgv.size(); ++i) {
      unsigned Size = InputArgv[i].size()+1;
      char *Dest = new char[Size];
      DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
      
      std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
      Dest[Size-1] = 0;
      
      // Endian safe: Result[i] = (PointerTy)Dest;
      EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i),
                             Type::LongTy);
    }
    Result[InputArgv.size()] = 0;
    return Result;
  } else {                                      // 32 bit target?
    int *Result = new int[InputArgv.size()+1];
    DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");

    for (unsigned i = 0; i < InputArgv.size(); ++i) {
      unsigned Size = InputArgv[i].size()+1;
      char *Dest = new char[Size];
      DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
      
      std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
      Dest[Size-1] = 0;
      
      // Endian safe: Result[i] = (PointerTy)Dest;
      EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i),
                             Type::IntTy);
    }
    Result[InputArgv.size()] = 0;  // null terminate it
    return Result;
  }
}

/// callAsMain - Call the function named FnName from M as if its
/// signature were int main (int argc, char **argv, const char
/// **envp), using the contents of Args to determine argc & argv, and
/// the contents of EnvVars to determine envp.  Returns the result
/// from calling FnName, or -1 and prints an error msg. if the named
/// function cannot be found.
///
int callAsMain(ExecutionEngine *EE, ModuleProvider *MP,
               const std::string &FnName,
               const std::vector<std::string> &Args,
               const std::vector<std::string> &EnvVars) {
  Function *Fn = MP->getModule()->getNamedFunction(FnName);
  if (!Fn) {
    std::cerr << "Function '" << FnName << "' not found in module.\n";
    return -1;
  }
  std::vector<GenericValue> GVArgs;
  GenericValue GVArgc;
  GVArgc.IntVal = Args.size();
  GVArgs.push_back(GVArgc); // Arg #0 = argc.
  GVArgs.push_back(PTOGV(CreateArgv(EE, Args))); // Arg #1 = argv.
  GVArgs.push_back(PTOGV(CreateArgv(EE, EnvVars))); // Arg #2 = envp.
  return EE->run(Fn, GVArgs).IntVal;
}

//===----------------------------------------------------------------------===//
// main Driver function
//
int main(int argc, char **argv, char * const *envp) {
  cl::ParseCommandLineOptions(argc, argv,
                              " llvm interpreter & dynamic compiler\n");

  // Load the bytecode...
  std::string ErrorMsg;
  ModuleProvider *MP = 0;
  try {
    MP = getBytecodeModuleProvider(InputFile);
  } catch (std::string &err) {
    std::cerr << "Error parsing '" << InputFile << "': " << err << "\n";
    exit(1);
  }

  ExecutionEngine *EE =
    ExecutionEngine::create(MP, ForceInterpreter);
  assert(EE && "Couldn't create an ExecutionEngine, not even an interpreter?");

  // If the user specifically requested an argv[0] to pass into the program, do
  // it now.
  if (!FakeArgv0.empty()) {
    InputFile = FakeArgv0;
  } else {
    // Otherwise, if there is a .bc suffix on the executable strip it off, it
    // might confuse the program.
    if (InputFile.rfind(".bc") == InputFile.length() - 3)
      InputFile.erase(InputFile.length() - 3);
  }

  // Add the module's name to the start of the vector of arguments to main().
  InputArgv.insert(InputArgv.begin(), InputFile);

  // Run the main function!
  int ExitCode = callAsMain(EE, MP, MainFunction, InputArgv,
                            makeStringVector(envp)); 

  // Now that we are done executing the program, shut down the execution engine
  delete EE;
  return ExitCode;
}