NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
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