-
Notifications
You must be signed in to change notification settings - Fork 4
/
utility.c
96 lines (79 loc) · 2.67 KB
/
utility.c
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
#include "zero-to-rust-jit.h"
LLVMOrcLLJITRef JitInst = NULL;
LLVMOrcThreadSafeContextRef CtxInst = NULL;
int handleError(LLVMErrorRef Err) {
char *ErrMsg = LLVMGetErrorMessage(Err);
fprintf(stderr, "Error: %s\n", ErrMsg);
LLVMDisposeErrorMessage(ErrMsg);
return 1;
}
const char *init(int argc, const char *argv[], LLVMOrcLLJITRef *Jit,
LLVMOrcThreadSafeContextRef *Ctx) {
if (argc < 2) {
const char *BaseName = strrchr(argv[0], '/');
const char *ExecName = BaseName ? BaseName + 1 : "zero-to-rust-jit";
fprintf(stderr, "Usage: %s sum.bc [ llvm-flags ]\n", ExecName);
shutdown(EXIT_FAILURE); // noreturn
}
LLVMParseCommandLineOptions(argc, argv, "");
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
// Keep local copies for simplicity (it's all opaque pointers)
LLVMErrorRef Err = LLVMOrcCreateLLJIT(&JitInst, 0);
if (Err)
shutdown(handleError(Err)); // noreturn
CtxInst = LLVMOrcCreateNewThreadSafeContext();
*Jit = JitInst;
*Ctx = CtxInst;
return argv[1];
}
LLVMOrcJITDylibRef addModule(LLVMOrcLLJITRef Jit, LLVMModuleRef Mod) {
LLVMOrcThreadSafeModuleRef TSM =
LLVMOrcCreateNewThreadSafeModule(Mod, CtxInst);
LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(Jit);
// If adding the ThreadSafeModule fails then we need to clean it up
// ourselves. If adding it succeeds the JIT will manage the memory.
LLVMErrorRef Err = LLVMOrcLLJITAddLLVMIRModule(Jit, MainJD, TSM);
if (Err) {
LLVMOrcDisposeThreadSafeModule(TSM);
shutdown(handleError(Err)); // noreturn
}
return MainJD;
}
void loop(int (*Sum)(int, int)) {
char answer;
do {
int a, b;
printf("a = ");
if (scanf("%x", &a) != 1)
shutdown(EXIT_FAILURE);
printf("b = ");
if (scanf("%x", &b) != 1)
shutdown(EXIT_FAILURE);
int Result = Sum(a, b);
printf("%i + %i = %i\n", a, b, Result);
printf("Again? (y/n) ");
if (scanf(" %c", &answer) != 1)
shutdown(EXIT_FAILURE);
printf("\n");
} while (answer == 'y' || answer == 'Y');
}
void shutdown(int ExitCode) {
if (JitInst) {
// Destroy our JIT instance. This will clean up any memory that the JIT has
// taken ownership of. This operation is non-trivial (e.g. it may need to
// JIT static destructors) and may also fail. In that case we want to render
// the error to stderr, but not overwrite any existing return value.
LLVMErrorRef Err = LLVMOrcDisposeLLJIT(JitInst);
if (Err) {
int JITShutdownExitCode = handleError(Err);
if (ExitCode == 0)
ExitCode = JITShutdownExitCode;
}
}
if (CtxInst) {
LLVMOrcDisposeThreadSafeContext(CtxInst);
}
LLVMShutdown();
exit(ExitCode);
}