|
19 | 19 | #include "heavy/Value.h" |
20 | 20 | #include "llvm/ADT/StringExtras.h" |
21 | 21 | #include "llvm/Support/Casting.h" |
| 22 | +#include "llvm/Support/DynamicLibrary.h" |
22 | 23 | #include "cassert" |
23 | 24 | #include "memory" |
24 | 25 |
|
@@ -93,6 +94,8 @@ heavy::ExternFunction source_loc; |
93 | 94 | heavy::ExternFunction source_loc_valid; |
94 | 95 | heavy::ExternFunction dump_source_loc; |
95 | 96 | heavy::ExternFunction make_syntactic_closure; |
| 97 | +heavy::ExternFunction load_plugin; |
| 98 | +heavy::ExternFunction load_builtin; |
96 | 99 |
|
97 | 100 | heavy::ExternFunction eval; |
98 | 101 | heavy::ExternFunction op_eval; |
@@ -1250,6 +1253,45 @@ void make_syntactic_closure(Context& C, ValueRefs Args) { |
1250 | 1253 | Value Result = C.CreateSyntaxClosure(Loc, Expr, Env); |
1251 | 1254 | C.Cont(Result); |
1252 | 1255 | } |
| 1256 | + |
| 1257 | +// Dynamically load a native shared library. |
| 1258 | +void load_plugin(Context& C, ValueRefs Args) { |
| 1259 | + if (Args.size() != 1) |
| 1260 | + return C.RaiseError("invalid arity"); |
| 1261 | + |
| 1262 | + llvm::StringRef Filename = Args.front().getStringRef(); |
| 1263 | + if (Filename.empty()) |
| 1264 | + return C.RaiseError("expecting nonempty string-like object: {}", |
| 1265 | + Args.front()); |
| 1266 | + |
| 1267 | + std::string ErrMsg; |
| 1268 | + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename.data(), |
| 1269 | + &ErrMsg)) { |
| 1270 | + // TODO Make a "note" with Msg. |
| 1271 | + String* Msg = C.CreateString(ErrMsg); |
| 1272 | + return C.RaiseError("Failed to load plugin: {}\n{}", {Args.front(), Msg}); |
| 1273 | + } |
| 1274 | + |
| 1275 | + C.Cont(); |
| 1276 | +} |
| 1277 | + |
| 1278 | +// Dynamically load a Builtin from a heavy::ValueFn. |
| 1279 | +void load_builtin(Context& C, ValueRefs Args) { |
| 1280 | + if (Args.size() != 1) |
| 1281 | + return C.RaiseError("invalid arity"); |
| 1282 | + |
| 1283 | + llvm::StringRef FuncName = Args.front().getStringRef(); |
| 1284 | + if (FuncName.empty()) |
| 1285 | + return C.RaiseError("expecting nonempty string-like object: {}", |
| 1286 | + Args.front()); |
| 1287 | + |
| 1288 | + void* FuncVoidPtr |
| 1289 | + = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(FuncName.data()); |
| 1290 | + if (FuncVoidPtr == nullptr) |
| 1291 | + return C.RaiseError("unable to load builtin: {}", Args.front()); |
| 1292 | + heavy::ValueFn Fn = reinterpret_cast<heavy::ValueFn>(FuncVoidPtr); |
| 1293 | + C.Cont(C.CreateBuiltin(Fn)); |
| 1294 | +} |
1253 | 1295 | } // end of namespace heavy::builtins |
1254 | 1296 |
|
1255 | 1297 | // initialize the module for run-time independent of the compiler |
@@ -1346,6 +1388,8 @@ void HEAVY_BASE_INIT(heavy::Context& Context) { |
1346 | 1388 | HEAVY_BASE_VAR(apply) = heavy::builtins::apply; |
1347 | 1389 | HEAVY_BASE_VAR(make_syntactic_closure) |
1348 | 1390 | = heavy::builtins::make_syntactic_closure; |
| 1391 | + HEAVY_BASE_VAR(load_plugin) = heavy::builtins::load_plugin; |
| 1392 | + HEAVY_BASE_VAR(load_builtin) = heavy::builtins::load_builtin; |
1349 | 1393 | } |
1350 | 1394 |
|
1351 | 1395 | // initializes the module and loads lookup information |
@@ -1444,6 +1488,8 @@ void HEAVY_BASE_LOAD_MODULE(heavy::Context& Context) { |
1444 | 1488 | {"source-value?", HEAVY_BASE_VAR(is_source_value)}, |
1445 | 1489 | {"apply", HEAVY_BASE_VAR(apply)}, |
1446 | 1490 | {"make-syntactic-closure", HEAVY_BASE_VAR(make_syntactic_closure)}, |
| 1491 | + {"load-plugin", HEAVY_BASE_VAR(load_plugin)}, |
| 1492 | + {"load-builtin", HEAVY_BASE_VAR(load_builtin)}, |
1447 | 1493 | }); |
1448 | 1494 | } |
1449 | 1495 |
|
|
0 commit comments