LLVM C++ API bitcode loading and execution - llvm

I am looking for a full sample that covers usage of the LLVM C++ API, particularly loading a function from a bitcode (not a typo, they call it bitcode) file, running it and get the results. I have studied this blog post and I am trying to port it to C++ but I am struggling to understand how to create the various instances needed, particularly the execution engine. I am using clang -c -emit-llvm file.c to compile a C file to a .bc LLVM bitcode file. The command clang -S -emit-llvm file.c also works and generates a textual .ll file. The function parseIRFile seems to be able to load both.
This is what I have so far:
LLVMContext context;
SMDiagnostic error;
unique_ptr<Module> mod = parseIRFile(StringRef(pathToLlOrBcFile), error, context);
I does not have to use JIT, I am fine with the basic interpreter for now; but I wish to make it work with MCJIT or whatever it's called later on.
Thanks to #arnt for noticing that I was actually using the IR text format; I changed the Makefile and the C++ app to reflect the fact that both .ll and .bc can be parsed by the same function.

I am using llvm-devel.x86_64 9.0.1-5.fc31 on Fedora 31. Full code below.
main.cc (This is the C++ app that loads the LLVM bitcode)
#include <iostream>
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/GenericValue.h>
using std::unique_ptr;
using std::cout;
using std::endl;
using llvm::Module;
using llvm::SMDiagnostic;
using llvm::LLVMContext;
using llvm::parseIRFile;
using llvm::StringRef;
using llvm::ExecutionEngine;
using llvm::EngineBuilder;
using llvm::ArrayRef;
using llvm::GenericValue;
using llvm::Function;
int main(int argc, char const *argv[]) {
LLVMContext context;
SMDiagnostic error;
unique_ptr<Module> mod = parseIRFile(StringRef("hosted.bc" /* .ll files also work */), error, context);
ExecutionEngine *executionEngine = EngineBuilder(std::move(mod)).setEngineKind(llvm::EngineKind::Interpreter).create();
Function *add = executionEngine->FindFunctionNamed(StringRef("add"));
GenericValue param1, param2;
param1.FloatVal = 5.5;
param2.FloatVal = 2.7;
GenericValue params[] = { param1, param2 };
ArrayRef<GenericValue> args = ArrayRef<GenericValue>(params, 2);
GenericValue result = executionEngine->runFunction(add, args);
cout << param1.FloatVal << " + " << param2.FloatVal << " = " << result.FloatVal << endl;
}
hosted.c (This is a C app that I compile into an .bc file with clang)
float add(float a, float b) {
return a + b;
}
Makefile (Used to compile the native app and the LLVM bytecode to be hosted in it)
app.o: main.cc
g++ main.cc -lLLVM -o app.o
hosted.bc: hosted.c
clang -c -emit-llvm hosted.c
clean:
rm app.o
rm hosted.bc
.PHONY: clean
Output (Compiling and running)
[dario#localhost llvm-cpp-first]$ make hosted.bc && make && ./app.o
clang -c -emit-llvm hosted.c
g++ main.cc -lLLVM -o app.o
5.5 + 2.7 = 8.2

Related

No bsoncxx for MongoDB C++ driver demo compilation

Hello, I want to compile some demo of mongodb-C++ API.
I follow the official guide:
http://mongocxx.org/mongocxx-v3/installation/
It is OK for step 1-5.
For use custom bson and mongocxx, I run the additional command as recommend:
In the event that you are building the BSON C++ library and/or the C++
driver to embed with other components and you wish to avoid the
potential for collision with components installed from a standard
build or from a distribution package manager, you can make use of the
BSONCXX_OUTPUT_BASENAME and MONGOCXX_OUTPUT_BASENAME options to cmake.
cmake .. \
-DBSONCXX_OUTPUT_BASENAME=custom_bsoncxx \
-DMONGOCXX_OUTPUT_BASENAME=custom_mongocxx
The mongo-db demo is used:
#include <iostream>
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
int main(int, char**) {
mongocxx::instance inst{};
mongocxx::client conn{mongocxx::uri{}};
bsoncxx::builder::stream::document document{};
auto collection = conn["testdb"]["testcollection"];
document << "hello" << "world";
collection.insert_one(document.view());
auto cursor = collection.find({});
for (auto&& doc : cursor) {
std::cout << bsoncxx::to_json(doc) << std::endl;
}
}
When I run with the command:
c++ --std=c++11 test.cpp -o test $(pkg-config --cflags --libs libmongocxx)
It feedbacks some error:
#include <bsoncxx/builder/stream/document.hpp
It looks like the header file has not been included.
How can I resolve the problem?
Thanks & Regards!

LLVM: How do I write IR to file and run it?

I want to parse an IR file created with clang++ -S -emit-llvm test.cpp -o test.ir using the parseIRFile call, manipulate this IR a bit, and then write the IR back to a file.
I've tried using the WriteBitcodeToFile call, but this doesn't work as expected.
How would I write the Module back to IR, and then compile and run the modified IR?
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Support/FileSystem.h>
using namespace llvm;
int main()
{
LLVMContext context;
SMDiagnostic error;
std::unique_ptr<Module> m = parseIRFile("test.ir", error, context);
std::error_code EC;
llvm::raw_fd_ostream OS("module", EC, llvm::sys::fs::F_None);
WriteBitcodeToFile(m.get(), OS);
OS.flush();
return 0;
}
An easy way to do it is dumping your module to stdout using:
m->dump();
Then you can redirect the output of your C++ program to a text file and compile it using llc :
llc < sample_module.ll > sample_module.s
You can also use the print function:
void print (raw_ostream &OS, AssemblyAnnotationWriter *AAW, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
What you need is to write an LLVM pass which allows you to go through the code Function by Function/Module by Module and read/modify/write to it. You can run this pass on your bytecode file using opt command and it will return the modified bytecode file which you can use.
Here are some sources for writing a pass:
1) http://llvm.org/docs/WritingAnLLVMPass.html
2) https://www.cs.cornell.edu/~asampson/blog/llvm.html
IR is not human readable. You can use llvm-dis to convert it to the human readable version like #TartanLlama said. You can run bitcode using lli command. After you modify the IR, you will see your modified IR running with lli.

Linking g++ compiled code against libraries created by clang++

In my Homebrew installation my libraries are compiled with clang, whereas I would like to, for performance reasons, compile my scientific code with gcc. In order to understand this problem better, I have created a minimal test:
// FILE print.cxx
#include <string>
#include <iostream>
void print_message(const std::string& message)
{
std::cout << message << std::endl;
}
// FILE test.cxx
#include <string>
void print_message(const std::string&);
int main()
{
std::string message = "Hello World!";
print_message(message);
return 0;
}
This code I compile with:
// SCRIPT compile.sh
clang++ -stdlib=libstdc++ -c print.cxx
g++ test.cxx print.o
The example that I have added works, but is it possible to make it work with libraries that are compiled without the -stdlib=libstdc++ flag and instead use the libc++?

can't run a c++ file - Eclipse Yoxos

I downloaded Eclipse from Yoxos. This Eclispe includes: c, cpp, java etc..
However, when I opened a new cpp project with MinGW GCC Toolchains, and created a cpp file: hello.cpp, and wrote the following little program:
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
when I run the file, it said - hello.exe has stopped working.
However, When I changed the program to:
(first line in comment)
//#include <iostream>
#include <stdio.h>
int main() {
printf("dsd");
return 0;
}
It worked well!
and when I removed the first line from comment like this:
#include <iostream>
#include <stdio.h>
int main() {
printf("dsd");
return 0;
}
the problem was back.. :(
Someone, Help..?
Thanks in advance! :)
Build Console Output:
20:41:10 **** Incremental Build of configuration Release for project hello ****
Info: Internal Builder is used for build
g++ -O3 -Wall -c -fmessage-length=0 -o helo.o "..\\helo.cpp"
g++ -o hello.exe helo.o
20:41:11 Build Finished (took 610ms)

Code with XCppRefl does not work

I am trying to use XCppRefl lib to achieve reflections in c++. http://www.extreme.indiana.edu/reflcpp/. I could successfully install this library in linux and run the tests given with the source code of the library.
Here is the code that I have written --
#include <iostream>
using namespace std;
#include <reflcpp/ClassType_tmpl.hpp>
#include <reflcpp/BoundClassType_tmpl.hpp>
#include <reflcpp/Exceptions.hpp>
using namespace reflcpp;
#include "Complex.h"
int main()
{
//ClassType ct = ClassType::getClass( string("Complex") );
////PtrHolder_smptr_t obj = ct.createInstance();
//assert(ct.name() == "B");
Complex x;
int ret;
Complex a;
ClassType c = ClassType::getClass( string("Complex") );
//cout<<"name :: "<<c.name()<<endl;
}
It seems to compile just fine --
$ g++ -g -I /usr/local/include/reflcpp-0.2/ -L /usr/local/include/reflcpp-0.2/ -lreflcpp main.cpp
However when I execute the executable (a.out), I get a core-dump
a.out: Type.cpp:87: static const reflcpp::Type_body* reflcpp::Type_body::getType(const std::string&): Assertion `s_class_name_map' failed.
Aborted (core dumped)
Does anyone has used this lib before? Please help.
you have to link your main.o to libreflcpp.a . after compiling use this:
g++ -p -pg -o"project_name" ./A.o ./A_reflection.o ./main.o /usr/local/lib/libreflcpp.a