NewLang Project
Yet another programm language
Main Page
Namespaces
Classes
Files
File List
File Members
Loading...
Searching...
No Matches
lib
test
llvm_test.cpp
Go to the documentation of this file.
1
//#ifdef BUILD_UNITTEST
2
//
3
//#include "warning_push.h"
4
//#include <gtest/gtest.h>
5
//#include "warning_pop.h"
6
//
7
//#include "jit.h"
8
//
10
//
11
//using namespace newlang;
12
//
14
// * Функции и классы для вызова изнутри JIT
15
// */
16
//namespace ns_stub {
17
//
18
// int func_stub(int arg1, short arg2) {
19
// return arg1*arg2;
20
// };
21
//
22
// int func_extern_stub() {
23
// return 4242;
24
// };
25
//
26
// class class_stub {
27
// public:
28
// int field_1;
29
// static int static_field_2;
30
//
31
// static class_stub * create(int a1, int a2) {
32
// return new class_stub(a1, a2);
33
// }
34
//
35
// class_stub() {
36
// printf("Call constructor class_stub()\n");
37
// field_1 = 0;
38
// }
39
//
40
// class_stub(int arg1, int arg2) {
41
// printf("Call constructor class_stub(%d, %d)\n", arg1, arg2);
42
// field_1 = arg1;
43
// static_field_2 = arg2;
44
// }
45
//
46
// virtual ~class_stub() {
47
// printf("Call virtual ~class_stub()\n");
48
// }
49
//
50
// int method_sum() {
51
//
52
// return field_1 + static_field_2;
53
// }
54
//
55
// int method_field1(int arg) {
56
//
57
// return field_1;
58
// }
59
//
60
// virtual double method_virt2() {
61
//
62
// return 999999999;
63
// }
64
//
65
// virtual float method_virt() {
66
//
67
// return 3.14 + field_1;
68
// }
69
//
70
// static float method_static() {
71
// return 3.1415;
72
// }
73
// };
74
//
75
// int class_stub::static_field_2 = 0;
76
//
77
// class class_full {
78
// public:
79
//
80
// class_full() {
81
// }
82
//
83
// int method() {
84
// return 42;
85
// }
86
// };
87
//};
88
//
90
// * Строка прототип для компиляции в JIT
91
// */
92
//const char * func_text_jit = ""
93
// "extern \"C\" int printf(const char *, ...);\n"
94
// "extern \"C\" int nv_add(int a, int b) {"
95
// " printf(\"call nv_add(%d, %d)\\n\", a, b);"
96
// " return a + b;"
97
// "};\n"
98
// ""
99
// "extern \"C\" int nv_sub(int a, int b) {"
100
// " printf(\"call nv_sub(%d, %d)\\n\", a, b);"
101
// " return a - b;"
102
// "};\n"
103
// "extern \"C\" int run(){"
104
// " nv_add(100, 123);"
105
// " nv_sub(100, 123);"
106
// " return 42;"
107
// "};\n"
108
// ""
109
// "namespace ns_stub {"
110
// " class run_internal {"
111
// " public:\n"
112
// " run_internal(){};"
113
// " int method(){"
114
// " return 43;"
115
// " };"
116
// " };"
117
// " class class_full {"
118
// " public:\n"
119
// " class_full();"
120
// " int method();"
121
// " };"
122
// ""
123
// " class class_stub {"
124
// " public:\n"
125
// " static class_stub * create(int, int);"
126
// " class_stub();"
127
// " class_stub(int arg1, int arg2);"
128
// " int method_sum();"
129
// " int method_field1(int);"
130
// " virtual float method_virt();"
131
// " };"
132
// ""
133
// "};"
134
// "extern \"C\" int run_internal(){"
135
// " ns_stub::run_internal cl_int;"
136
// " printf(\"run_internal.method %d\\n\", cl_int.method());"
137
// " return 44;"
138
// "};\n"
139
// ""
140
// "extern \"C\" int run_stub(){"
141
// " ns_stub::class_stub *cl = ns_stub::class_stub::create(123, 123);"
142
// " printf(\"class_stub.method_sum %d\\n\", cl->method_sum());"
143
// " delete cl;"
144
// " return 42;"
145
// "};\n"
146
// ""
147
// "extern \"C\" int run_extern();"
148
// "extern \"C\" int run_extern_stub(){"
149
// " return run_extern();"
150
// "};\n"
151
// "extern \"C\" int run_virt(){"
152
// " ns_stub::class_stub *cl = ns_stub::class_stub::create(124, 125);"
153
// " printf(\"class_stub.method_virt %f\\n\", cl->method_virt());"
154
// " delete cl;"
155
// " return 0;"
156
// "};\n"
157
// "";
158
//
159
//
160
//
161
//#define DEBUG_MSG(msg) std::cout << "[DEBUG]: "<<msg<< std::endl;
162
//
188
//
189
//std::unique_ptr<llvm::Module> CompileCpp(std::string source, std::vector<std::string> opts, std::string *asm_code = nullptr) {
190
// clang::CompilerInstance compilerInstance;
191
// auto& compilerInvocation = compilerInstance.getInvocation();
192
//
193
//
194
// // Диагностика работы Clang
195
// clang::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new clang::DiagnosticOptions;
196
// clang::TextDiagnosticPrinter *textDiagPrinter =
197
// new clang::TextDiagnosticPrinter(llvm::outs(), &*DiagOpts);
198
//
199
// clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> pDiagIDs;
200
//
201
// clang::DiagnosticsEngine *pDiagnosticsEngine =
202
// new clang::DiagnosticsEngine(pDiagIDs, &*DiagOpts, textDiagPrinter);
203
//
204
//
205
// // Целевая платформа
206
// std::string triple = LLVMGetDefaultTargetTriple();
207
//
208
// std::vector<std::string> itemstrs;
209
// itemstrs.push_back(triple.insert(0, "-triple="));
210
// itemstrs.push_back("-xc++");
211
// itemstrs.push_back("-std=c++23");
212
//
213
// itemstrs.insert(itemstrs.end(), opts.begin(), opts.end());
214
//
215
// // itemstrs.push_back("-fno-exceptions");
216
// // itemstrs.push_back("-funwind-tables");
217
//
218
// std::vector<const char*> itemcstrs;
219
// for (unsigned idx = 0; idx < itemstrs.size(); idx++) {
220
// // note: if itemstrs is modified after this, itemcstrs will be full
221
// // of invalid pointers! Could make copies, but would have to clean up then...
222
// itemcstrs.push_back(itemstrs[idx].c_str());
224
// }
225
//
226
// // Компиляция из памяти
227
// // Send code through a pipe to stdin
228
// int codeInPipe[2];
229
// pipe2(codeInPipe, O_NONBLOCK);
230
// write(codeInPipe[1], source.c_str(), source.size());
231
// close(codeInPipe[1]); // We need to close the pipe to send an EOF
232
// dup2(codeInPipe[0], STDIN_FILENO);
233
//
234
// itemcstrs.push_back("-"); // Read code from stdin
235
//
236
// clang::CompilerInvocation::CreateFromArgs(compilerInvocation,
237
// llvm::ArrayRef<const char *>(itemcstrs.data(),
238
// itemcstrs.size()), *pDiagnosticsEngine);
239
//
240
// auto& languageOptions = compilerInvocation.getLangOpts();
241
// auto& preprocessorOptions = compilerInvocation.getPreprocessorOpts();
242
// auto& targetOptions = compilerInvocation.getTargetOpts();
243
//
244
// auto& frontEndOptions = compilerInvocation.getFrontendOpts();
245
// // frontEndOptions.ShowStats = true;
246
//
247
// auto& headerSearchOptions = compilerInvocation.getHeaderSearchOpts();
248
// // headerSearchOptions.Verbose = true;
249
//
250
// auto& codeGenOptions = compilerInvocation.getCodeGenOpts();
251
//
252
//
253
// targetOptions.Triple = LLVMGetDefaultTargetTriple();
254
// compilerInstance.createDiagnostics(textDiagPrinter, false);
255
//
256
// DEBUG_MSG("Using target triple: " << triple);
257
//
258
// LLVMContextRef ctx = LLVMContextCreate();
259
// std::unique_ptr<clang::CodeGenAction> action = std::make_unique<clang::EmitLLVMOnlyAction>((llvm::LLVMContext *)ctx);
260
//
261
// assert(compilerInstance.ExecuteAction(*action));
262
//
263
// // Runtime LLVM Module
264
// std::unique_ptr<llvm::Module> module = action->takeModule();
265
//
266
// assert(module);
267
//
268
//
269
// if (asm_code) {
270
// llvm::raw_string_ostream asm_stream(*asm_code);
271
// module->print(asm_stream, 0, false);
272
// }
273
// //AssemblyWriter
274
//
275
//
276
//
277
//
278
// // LLVMContextRef context = LLVMContextCreate();
279
// // LLVMModuleRef module = LLVMModuleCreateWithNameInContext("test", context);
280
//
281
// // LLVMTypeRef f32 = LLVMFloatTypeInContext(context);
282
// // LLVMTypeRef ftype = LLVMFunctionType(f32, 0, 0, 0);
283
// // LLVMValueRef ftest = LLVMAddFunction(module, "ftest", ftype);
284
// // LLVMBasicBlockRef bb = LLVMAppendBasicBlockInContext(context, ftest, "ftest");
285
// // LLVMBuilderRef builder = LLVMCreateBuilderInContext(context);
286
// // LLVMPositionBuilderAtEnd(builder, bb);
287
// // LLVMValueRef v1 = LLVMConstReal(f32, 2.5);
288
// // LLVMValueRef v2 = LLVMConstReal(f32, 4.3);
289
// // LLVMValueRef result = LLVMBuildFAdd(builder, v1, v2, "f-add");
290
// // LLVMBuildRet(builder, result);
291
// // LLVMVerifyFunction(ftest, LLVMPrintMessageAction);
292
//
293
// char* errors = 0;
294
// // LLVMPrintModuleToFile((LLVMModuleRef)&*module, "include_h_i_function_test.s", &errors);
295
// // printf("error: %s\n", errors);
296
// // LLVMDisposeMessage(errors);
297
//
298
// // LLVMInitializeAllTargetInfos();
299
// // LLVMInitializeAllTargets();
300
// // LLVMInitializeAllTargetMCs();
301
// // LLVMInitializeAllAsmParsers(); // Для использования ассемблерных вставок!!! (комменатрие в коде)
302
// // LLVMInitializeAllAsmPrinters();
303
//
304
// // LLVMTargetRef target;
305
// // LLVMGetTargetFromTriple(LLVMGetDefaultTargetTriple(), &target, &errors);
306
// // // printf("error: %s\n", errors);
307
// // LLVMDisposeMessage(errors);
308
// // // printf("target: %s, [%s], %d, %d\n", LLVMGetTargetName(target), LLVMGetTargetDescription(target), LLVMTargetHasJIT(target), LLVMTargetHasTargetMachine(target));
309
// // // printf("triple: %s\n", LLVMGetDefaultTargetTriple());
310
// // // printf("features: %s\n", LLVMGetHostCPUFeatures());
311
// // LLVMTargetMachineRef machine = LLVMCreateTargetMachine(target, LLVMGetDefaultTargetTriple(), "generic", LLVMGetHostCPUFeatures(), LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault);
312
// //
313
// // LLVMSetTarget((LLVMModuleRef)&*module, LLVMGetDefaultTargetTriple());
314
// // LLVMTargetDataRef datalayout = LLVMCreateTargetDataLayout(machine);
315
// // char* datalayout_str = LLVMCopyStringRepOfTargetData(datalayout);
316
// // // printf("datalayout: %s\n", datalayout_str);
317
// // LLVMSetDataLayout((LLVMModuleRef)&*module, datalayout_str);
318
// // LLVMDisposeMessage(datalayout_str);
319
// //
320
// // LLVMTargetMachineEmitToFile(machine, (LLVMModuleRef)&*module, "include_h_i_function_test.o", LLVMObjectFile, &errors);
321
// // // printf("error: %s\n", errors);
322
// // LLVMDisposeMessage(errors);
323
//
324
//
325
// // Оптимизация IR
326
// // llvm::PassBuilder passBuilder;
327
// // llvm::LoopAnalysisManager loopAnalysisManager;
328
// // llvm::FunctionAnalysisManager functionAnalysisManager;
329
// // llvm::CGSCCAnalysisManager cGSCCAnalysisManager;
330
// // llvm::ModuleAnalysisManager moduleAnalysisManager;
331
// //
332
// // passBuilder.registerModuleAnalyses(moduleAnalysisManager);
333
// // passBuilder.registerCGSCCAnalyses(cGSCCAnalysisManager);
334
// // passBuilder.registerFunctionAnalyses(functionAnalysisManager);
335
// // passBuilder.registerLoopAnalyses(loopAnalysisManager);
336
// // passBuilder.crossRegisterProxies(loopAnalysisManager, functionAnalysisManager, cGSCCAnalysisManager, moduleAnalysisManager);
337
// //
338
// // llvm::ModulePassManager modulePassManager = passBuilder.buildPerModuleDefaultPipeline(llvm::OptimizationLevel::O0);
339
// // modulePassManager.run(*module, moduleAnalysisManager);
340
//
341
// return module;
342
//}
343
//
344
//llvm::orc::ThreadSafeModule createDemoModule() {
345
// auto ctx = std::make_unique<llvm::LLVMContext>();
346
// auto M = std::make_unique<llvm::Module>("test", *ctx);
347
//
348
// // Create the add1 function entry and insert this entry into module M. The
349
// // function will have a return type of "int" and take an argument of "int".
350
// llvm::Function *Add1F = llvm::Function::Create(
351
// llvm::FunctionType::get(llvm::Type::getInt32Ty(*ctx),{llvm::Type::getInt32Ty(*ctx)}, false),
352
// llvm::Function::ExternalLinkage, "add1", M.get());
353
//
354
// // Add a basic block to the function. As before, it automatically inserts
355
// // because of the last argument.
356
// llvm::BasicBlock *BB = llvm::BasicBlock::Create(*ctx, "EntryBlock", Add1F);
357
//
358
// // Create a basic block builder with default parameters. The builder will
359
// // automatically append instructions to the basic block `BB'.
360
// llvm::IRBuilder<> builder(BB);
361
//
362
// // Get pointers to the constant `1'.
363
// llvm::Value *One = builder.getInt32(1);
364
//
365
// // Get pointers to the integer argument of the add1 function...
366
// assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg
367
// llvm::Argument *ArgX = &*Add1F->arg_begin(); // Get the arg
368
// ArgX->setName("AnArg"); // Give it a nice symbolic name for fun.
369
//
370
// // Create the add instruction, inserting it into the end of BB.
371
// llvm::Value *Add = builder.CreateAdd(One, ArgX);
372
//
373
// // Create the return instruction and add it to the basic block
374
// builder.CreateRet(Add);
375
//
376
// return llvm::orc::ThreadSafeModule(std::move(M), std::move(ctx));
377
//}
378
//
379
//TEST(LLVM, JIT) {
380
//
381
// llvm::ExitOnError ExitOnErr;
382
//
383
// ASSERT_TRUE(JIT::LLVMInitialize());
384
// // InitLLVM X(argc, argv);
385
//
386
//
387
// // cl::ParseCommandLineOptions(argc, argv, "HowToUseLLJIT");
388
// // ExitOnErr.setBanner(std::string(argv[0]) + ": ");
389
//
390
// std::string asm_source;
391
//
392
// // Create an LLJIT instance.
393
// auto J = ExitOnErr(llvm::orc::LLJITBuilder().create());
394
// // auto M = createDemoModule();
395
// auto module = CompileCpp(func_text_jit,{}, &asm_source);
396
//
397
// std::error_code EC;
398
// llvm::raw_fd_ostream OS("nv_add_JIT.bc", EC, llvm::sys::fs::OpenFlags::OF_None);
399
// llvm::WriteBitcodeToFile(*module, OS);
400
// OS.flush();
401
//
402
// auto M = llvm::orc::ThreadSafeModule(std::move(module), std::make_unique<llvm::LLVMContext>());
403
//
404
//
405
// std::ofstream asm_file("nv_add_JIT.s", std::ios::trunc);
406
// asm_file << asm_source;
407
// asm_file.close();
408
//
409
//
410
//
411
//
412
// std::string dump;
413
// llvm::raw_string_ostream err(dump);
414
//
415
//
416
// llvm::orc::ExecutionSession &ES = J->getExecutionSession();
417
//
418
// // JITDylib *plat = ES.getJITDylibByName("<Platform>");
419
// // assert(plat);
420
// // dump.clear();
421
// // plat->dump(err);
422
// // std::cout << "<Platform>:\n" << dump << "\n";
423
// //
424
// // JITDylib *proc = ES.getJITDylibByName("<Process Symbols>");
425
// // assert(proc);
426
// // dump.clear();
427
// // proc->dump(err);
428
// // std::cout << "<Process Symbols>:\n" << dump << "\n";
429
//
430
//
431
// ExitOnErr(J->addIRModule(std::move(M)));
432
// // ExitOnErr(J->addObjectFile(std::move(M)));
433
// // Adds an object file to the given JITDylib.
434
// //Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj)
435
//
436
//
437
//
438
//
439
// // Функция с именем run_extern отсуствует (JIT session error: Symbols not found: [ run_extern ])
440
// // Подставим вместо нее указатель на другу функцию, но с таким же прототипом (func_extern_stub)
441
// const llvm::orc::SymbolStringPtr Foo = ES.intern("run_extern");
442
// const llvm::orc::ExecutorSymbolDef FooSym(llvm::orc::ExecutorAddr::fromPtr(&ns_stub::func_extern_stub), llvm::JITSymbolFlags::Exported | llvm::JITSymbolFlags::Absolute);
443
// auto as = llvm::orc::absoluteSymbols({
444
// {Foo, FooSym}
445
// });
446
//
447
// ASSERT_FALSE(J->getMainJITDylib().define(as));
448
//
449
//
450
// llvm::Expected<llvm::orc::ExecutorAddr> test = J->lookup("nv_add");
451
// ASSERT_TRUE(!!test) << "lookup error:\n" << toString(test.takeError()) << ": lookup error3\n";
452
//
453
// DEBUG_MSG("Retrieving nv_add/nv_sub functions...");
454
//
455
// auto addAddr = ExitOnErr(J->lookup("nv_add"));
456
// int (*add)(int, int) = addAddr.toPtr<int(int, int) >();
457
// ASSERT_TRUE(add);
458
//
459
// int res = add(40, 2);
460
// ASSERT_TRUE(42 == res);
461
//
462
// auto subAddr = ExitOnErr(J->lookup("nv_sub"));
463
// int (*sub)(int, int) = subAddr.toPtr<int(int, int) >();
464
// ASSERT_TRUE(sub);
465
//
466
// res = sub(50, 7);
467
// ASSERT_TRUE(43 == res);
468
//
469
//
470
//
471
// printf("Call: run_internal\n");
472
// auto run_internalAddr = ExitOnErr(J->lookup("run_internal"));
473
// int (*run_internal)() = run_internalAddr.toPtr<int() >();
474
// ASSERT_TRUE(run_internal);
475
//
476
// res = run_internal();
477
// ASSERT_TRUE(44 == res);
478
//
479
//
480
// // Линкер удаяет не используемый код,
481
// // и если нет обращения к методу то его будет нельзя вызвать в JIT
482
// // JIT session error: Symbols not found: [ _ZN7ns_stub10class_stub6createEii, _ZN7ns_stub10class_stub10method_sumEv ]
483
// ns_stub::class_stub *cl = ns_stub::class_stub::create(0, 0);
484
// printf("Check run_stub.method %d\n", cl->method_sum());
485
// printf("Check run_stub.method_virt %f\n", cl->method_virt());
486
// delete cl;
487
//
488
//
489
// printf("Call: run_stub\n");
490
// auto run_stubAddr = ExitOnErr(J->lookup("run_stub"));
491
// int (*run_stub)() = run_stubAddr.toPtr<int() >();
492
// ASSERT_TRUE(run_stub);
493
//
494
// res = run_stub();
495
// ASSERT_TRUE(42 == res);
496
//
497
//
498
// printf("Call: run_extern_stub\n");
499
// auto run_extern_stubAddr = ExitOnErr(J->lookup("run_extern_stub"));
500
// int (*run_extern_stub)() = run_extern_stubAddr.toPtr<int() >();
501
// assert(run_extern_stub);
502
//
503
// res = run_extern_stub();
504
// ASSERT_TRUE(4242 == res);
505
//
506
//
507
// /*
508
// *
509
// * Так нельзя !!!!!
510
// * Виртуальные методы изнутри JIT вызываются неправильно при некорректном заголовочном файле!
511
// *
512
// * ERROR !!!!
513
// * Virtual methods from within JIT are called incorrectly when the header file is incorrect!
514
// *
515
// */
516
//
517
// // printf("Call: run_virt\n");
518
// // auto run_virtAddr = ExitOnErr(J->lookup("run_virt"));
519
// // int (*run_virt)() = run_virtAddr.toPtr<int() >();
520
// // ASSERT_TRUE(run_virt);
521
// //
522
// // res = run_virt();
523
// // ASSERT_TRUE(0 == res);
524
//}
525
//
526
//
527
//#include "object.h"
528
//#include "runtime.h"
529
//
530
//#pragma message WARNING("include_test.cpp excluded from build!!!")
531
//
774
//
775
//#endif // BUILD_UNITTEST
Generated by
1.11.0