forked from vladandrew/llvm-ei
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ExtensibleInterpreter.h
101 lines (84 loc) · 3.31 KB
/
ExtensibleInterpreter.h
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
#ifndef EXTENSIBLE_INTERPRETER_H
#define EXTENSIBLE_INTERPRETER_H
#include <vector>
#include "llvm/IR/InstVisitor.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IR/Module.h"
#include "ExecutionEngine/Interpreter/Interpreter.h"
// This is a GIANT HACK that should NOT BE TRUSTED. I need access to the
// private fields of Interpreter, so here I'm redefining a similar-looking
// class and hoping that the compiler lays it out the same as Interpreter. Then
// I cast an Interpreter* to a PublicInterpreter* to access its
// otherwise-inaccessible fields.
//
// This will almost certainly break at some point.
class PublicInterpreter : public llvm::ExecutionEngine,
public llvm::InstVisitor<llvm::Interpreter> {
public:
llvm::GenericValue ExitValue;
llvm::IntrinsicLowering *IL;
std::vector<llvm::ExecutionContext> ECStack;
std::vector<llvm::Function*> AtExitHandlers;
};
// ExtensibleInterpreter is a facade around Interpreter that allows subclasses
// to override one important method, execute(). This method is responsible for
// interpreting a single instruction. Subclasses can override it to do whatever
// they like, including calling the superclass' version of execute() to make
// interpretation continue as usual.
class ExtensibleInterpreter : public llvm::ExecutionEngine {
public:
llvm::Interpreter *interp;
PublicInterpreter *pubInterp; // GIANT HACK
llvm::Module *module;
explicit ExtensibleInterpreter(llvm::Module *M);
virtual ~ExtensibleInterpreter();
// Interpreter execution loop.
virtual void run();
virtual void execute(llvm::Instruction &I);
// Convenience entry point.
virtual int runMain(std::vector<std::string> args,
char * const *envp = 0);
// Satisfy the ExecutionEngine interface.
llvm::GenericValue runFunction(
llvm::Function *F,
llvm::ArrayRef<llvm::GenericValue> ArgValues
);
void *getPointerToNamedFunction(llvm::StringRef,
bool AbortOnFailure = true);
void *recompileAndRelinkFunction(llvm::Function *F);
void freeMachineCodeForFunction(llvm::Function *F);
void *getPointerToFunction(llvm::Function *F);
void *getPointerToBasicBlock(llvm::BasicBlock *BB);
};
// Utility for parsing and running a bitcode file with your interpreter.
template <typename InterpreterType>
int interpret(std::string bitcodeFile, std::vector<std::string> args,
char * const *envp) {
llvm::LLVMContext Context;
// Load the bitcode.
llvm::SMDiagnostic Err;
auto M = llvm::parseIRFile(bitcodeFile, Err, Context);
llvm::Module *Mod = M.release();
if (!Mod) {
llvm::errs() << "bitcode parsing failed\n";
return -1;
}
// Load the whole bitcode file eagerly to check for errors.
std::string ErrorMsg;
if (llvm::Error EC = Mod->materializeAll()) {
llvm::errs() << "bitcode read error: " << ErrorMsg << "\n";
return -1;
}
// Remove ".bc" suffix from input bitcode name and use it as argv[0].
if (llvm::StringRef(bitcodeFile).endswith(".bc"))
bitcodeFile.erase(bitcodeFile.length() - 3);
args.insert(args.begin(), bitcodeFile);
// Create and run the interpreter.
ExtensibleInterpreter *interp = new InterpreterType(Mod);
int retcode = interp->runMain(args, envp);
//delete interp;
exit(0);
return retcode;
}
#endif