Issue with LLVM JIT (LLJIT) - llvm

I am following a tutorial on making JIT compiler with LLVM (code is shown below and most recent version of LLVM is used). Everything works other than this line (if I comment this function, code compiles):
return (T)symbol.get().getAddress();
which gives the following error:
JIT.cpp:22:29: error: ‘std::remove_reference_t<llvm::orc::ExecutorAddr> {aka class llvm::orc::ExecutorAddr}’ has no member named ‘getAddress’
return (T)symbol.get().getAddress();
Code
#pragma once
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <memory>
#include <type_traits>
namespace FooLang
{
class JIT
{
private:
std::unique_ptr<llvm::orc::LLJIT> lljit;
public:
JIT(std::unique_ptr<llvm::orc::LLJIT> _lljit) : lljit(std::move(_lljit)) {}
void registerSymbols(
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)> symbolMap) {
auto &mainJitDylib = this->lljit->getMainJITDylib();
llvm::cantFail(mainJitDylib.define(
absoluteSymbols(symbolMap(llvm::orc::MangleAndInterner(
mainJitDylib.getExecutionSession(), this->lljit->getDataLayout())))));
}
template <typename T, typename = std::enable_if_t<std::is_pointer<T>::value && std::is_function<std::remove_pointer_t<T>>::value>>
llvm::Expected<T> lookup(const std::string &name)
{
auto symbol = this->lljit->lookup(name);
if (!symbol)
{
return symbol.takeError();
}
return (T)symbol.get().getAddress();
}
template <typename T, typename = std::enable_if_t<std::is_function<T>::value>>
inline llvm::Expected<T *> lookup(const std::string &name)
{
return this->lookup<T *>(name);
}
static llvm::Expected<JIT> create(std::unique_ptr<llvm::Module> &module, std::unique_ptr<llvm::LLVMContext> &context)
{
auto lljit = llvm::orc::LLJITBuilder().create();
auto &jd = lljit.get()->getMainJITDylib();
jd.addGenerator(llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess('_')));
if (!lljit)
{
return lljit.takeError();
}
if (auto err = lljit.get()->addIRModule(llvm::orc::ThreadSafeModule(std::move(module), std::move(context))))
{
return std::move(err);
}
return JIT(std::move(lljit.get()));
}
};
} // namespace FooLang
And it is used like following:
int run(IRgen* ir_gen)
{
auto jit = JIT::create(ir_gen->module, ir_gen->llvm_context);
jit->registerSymbols(
[&](llvm::orc::MangleAndInterner interner) {
llvm::orc::SymbolMap symbolMap;
// Add symbols here
symbolMap[interner("printf")] = llvm::JITEvaluatedSymbol::fromPointer(printf);
return symbolMap;
});
auto entry = jit->lookup<int()>("main");
if (!entry)
{
llvm::errs() << entry.takeError();
return 1;
}
return entry.get()();
}

In a recent change auto symbol = this->llvmjit->lookup(name); will return an ExecutorAddr instead of a JITEvaluatedSymbols, see: https://reviews.llvm.org/rG16dcbb53dc7968a3752661aac731172ebe0faf64
Your pasted code returns a template parameter type T and doesn't show the caller so I can't see what you intend to return. My suggestion is that you probably want to use ExecutorAddr::toPtr but I can't be sure.

Related

std::function & std::forward with variadic templates

Recently I was reading about variadic templates and based on an example I've seen online I was trying to implement a basic event-system. So far it seems to work fine but I was trying to go a step further and allow N number of arguments to be passed to an event handler function / callback, unfortunately the build error I'm getting is the following and I'm not sure what I'm doing wrong. I looked into similar source codes but still cant figure out what's the issue.
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: error: parameter packs not expanded with '...':
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: note: 'Args'
Build finished with error(s).
Here is what I have so far, if you remove the ... the event system works fine for the 2 registered events in main.
#include <any>
#include <string>
#include <iostream>
#include <functional>
#include <unordered_map>
class EventEmitter
{
private:
std::unordered_map<std::string, std::any> events;
public:
EventEmitter() {}
void on(const std::string &eventName, const std::any &eventCallback)
{
events[eventName] = eventCallback;
}
template <typename R>
R emit(const std::string &eventName)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(void)>>(eventCallback)();
}
template <typename R, typename... Args>
R emit(const std::string &eventName, Args &&...args)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
}
virtual ~EventEmitter() {}
};
int fun1()
{
std::cout << "fun1" << std::endl;
return 1;
}
double fun2(int i)
{
std::cout << "fun2" << std::endl;
return double(i);
}
double fun3(int x, int y)
{
std::cout << "fun3" << std::endl;
return double(x + y);
}
int main(int argc, char *argv[])
{
EventEmitter e;
e.on("fun1", std::function<int(void)>(fun1));
e.on("fun2", std::function<double(int)>(fun2));
e.emit<int>("fun1");
e.emit<double, int>("fun2", 1);
// Variadic would have been handy right here I guess?
// e.on("fun3", std::function<double(int, int)>(fun3));
// e.emit<double, int>("fun3", 1, 2);
return 0;
}
How can I fix this?
Well, you need to expand it.
return std::any_cast<std::function<R(Args...)>>(eventCallback)(std::forward<Args>(args)...);
^^^^^^^

List WPA supplicant network properties using dbus-cpp

When trying to list network properties - https://w1.fi/wpa_supplicant/devel/dbus.html#dbus_network using dbus-cpp I get a number of errors about missing operator== for core::dbus::types::Variant
/usr/include/core/dbus/impl/object.h:185:17: required from ‘std::shared_ptr<core::dbus::Property<PropertyDescription> > core::dbus::Object::get_property() [with PropertyDescription = fi::w1::wpa_supplicant1::Network::Properties::Propertiez]’ /home/martin/ClionProjects/ang-wifi-controller/src/wpasupplicantclient.cpp:149:118: required from here /usr/include/c++/6/bits/stl_pair.h:364:51: error: no match for ‘operator==’ (operand types are ‘const core::dbus::types::Variant’ and ‘const core::dbus::types::Variant’)
{ return __x.first == __y.first && __x.second == __y.second; }
My code is based on dbus-cpp examples and http://quaintous.com/2015/08/30/cpp11-dbus/, but they only offer limited assistance.
The code representing Properties property is as follows:
namespace fi {
namespace w1 {
struct wpa_supplicant1 {
struct Network {
struct Properties {
struct Propertiez {
inline static std::string name() { return "Properties"; };
typedef Network Interface;
typedef std::map<std::string, core::dbus::types::Variant> ValueType;
static const bool readable = true;
static const bool writable = true;
};
};
};
And the offending line in .cpp is networkProxy->get_property<fi::w1::wpa_supplicant1::Network::Properties::Propertiez>();
I found that this question has already been asked at https://answers.launchpad.net/ubuntu/+source/dbus-cpp/+question/593271, but nobody offered any advice. Going through the code of packages listed by apt-cache rdepends libdbus-cpp5 also yielded no results.
I tried messing with the ValueType but it all resulted in runtime errors as the expected result probably truly is the map. It honestly seems like a bug in the library to me, but since this must be an obvious use case I am trying to find the mistake in my usage of the library. So what am I doing wrong?
Edit: Since I did not get any response, I am including minimal sample.
#include <core/dbus/bus.h>
#include <core/dbus/object.h>
#include <core/dbus/property.h>
#include <core/dbus/service.h>
#include <core/dbus/result.h>
#include <core/dbus/asio/executor.h>
#include <core/dbus/interfaces/properties.h>
#include <core/dbus/types/stl/string.h>
#include <core/dbus/types/stl/tuple.h>
#include <core/dbus/types/stl/vector.h>
#include <core/dbus/types/struct.h>
#include <core/dbus/types/variant.h>
using namespace std::chrono_literals;
using DBusDict = std::map<std::string, core::dbus::types::Variant>;
namespace fi {
namespace w1 {
struct wpa_supplicant1
{
struct GetInterface {
typedef wpa_supplicant1 Interface;
static const std::string &name()
{
static const std::string s("GetInterface");
return s;
}
inline static const std::chrono::milliseconds default_timeout() { return 1s; }
};
struct Iface
{
struct AddNetwork {
typedef Iface Interface;
static const std::string &name()
{
static const std::string s("AddNetwork");
return s;
}
inline static const std::chrono::milliseconds default_timeout() { return 1s; }
};
struct Properties
{
struct Networks
{
inline static std::string name()
{ return "Networks"; };
typedef Iface Interface;
typedef std::vector<core::dbus::types::ObjectPath> ValueType;
static const bool readable = true;
static const bool writable = false;
};
};
};
struct Network
{
struct Properties
{
struct Propertiez
{
inline static std::string name()
{ return "Properties"; };
typedef Network Interface;
typedef DBusDict ValueType;
static const bool readable = true;
static const bool writable = true;
};
};
};
};
};
};
namespace core {
namespace dbus {
namespace traits {
template <> struct Service<fi::w1::wpa_supplicant1> {
inline static const std::string &interface_name()
{
static const std::string s("fi.w1.wpa_supplicant1");
return s;
}
};
template <> struct Service<fi::w1::wpa_supplicant1::Iface> {
inline static const std::string &interface_name()
{
static const std::string s("fi.w1.wpa_supplicant1.Interface");
return s;
}
};
template <> struct Service<fi::w1::wpa_supplicant1::Network> {
inline static const std::string &interface_name()
{
static const std::string s("fi.w1.wpa_supplicant1.Network");
return s;
}
};
}
}
}
int main()
{
//bus
auto systemBus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::system);
systemBus->install_executor(core::dbus::asio::make_executor(systemBus));
auto busThread = std::thread(std::bind(&core::dbus::Bus::run, systemBus));
//service
auto wpaService = core::dbus::Service::use_service<fi::w1::wpa_supplicant1>(systemBus);
auto wpaObjectPath = core::dbus::types::ObjectPath("/fi/w1/wpa_supplicant1");
auto wpaRootProxy = wpaService->object_for_path(wpaObjectPath);
//iface
auto ifacePath = wpaRootProxy->transact_method<fi::w1::wpa_supplicant1::GetInterface,
core::dbus::types::ObjectPath,
std::string>("wlan0"); //change this to your own wireless interface
auto wpaIfaceProxy = wpaService->object_for_path(ifacePath.value());
auto networkPaths = wpaIfaceProxy->get_property<fi::w1::wpa_supplicant1::Iface::Properties::Networks>();
//network
std::string ssid("network");
std::string password("password");
DBusDict args = {
{"ssid", core::dbus::types::Variant::encode(ssid)},
{"psk", core::dbus::types::Variant::encode(password)},
};
auto networkPath = wpaIfaceProxy->transact_method<fi::w1::wpa_supplicant1::Iface::AddNetwork,
core::dbus::types::ObjectPath,
DBusDict>(args);
auto networkProxy = wpaService->object_for_path(networkPath.value());
//get properties - uncomment line below to get compiler errors
//auto netProps = networkProxy->get_property<fi::w1::wpa_supplicant1::Network::Properties::Propertiez>();
while (true) {
continue;
}
}
Compile using: g++ $(pkg-config --cflags dbus-1 dbus-cpp) ./main.cpp $(pkg-config --libs dbus-1 dbus-cpp) -lpthread
Update:
dbus-cpp has an implementation for org.freedesktop.DBus.Properties.Get method.
Get:
auto resultVariant = dbus_object->invoke_method_synchronously
/*Method*/ <dbus::interfaces::Properties::Get,
/*Output Type*/ dbus::types::Variant,
/*Input Types*/ std::string, std::string>
("fi.w1.wpa_supplicant1.Network","Properties").value();
auto props = resultVariant.as<std::map<std::string, dbus::types::Variant>>();
Sadly, the Set method, while also implemented, does NOT seem to work with any ArgumentTypes with nested Variants within them. So:
a{sv} : std::map<std::string, core::dbus::types::Variant>
a{v} : std::vector<core::dbus::types::Variant>
in a Set method call will actually cause the program to crash. (Didn't test more)
Old post:
I ran into the same bug today and found a workaround for at least getting the properties value.
Instead of using
auto prop = dbus_object->get_property<fi::w1::wpa_supplicant1::Network::Properties::Propertiez>();
try
//returns std::map<std::string, core::dbus::types::Variant>>
auto props = dbus_object->get_all_properties<fi::w1::wpa_supplicant1::Network>();
auto prop = props["Properties"];
auto prop_value = prop.as<std::map<std::string, core::dbus::types::Variant>>();
As far as I understand the bug, dbus-cpp makes use of the
org.freedesktop.DBus.Properties interface to read out Properties.
So dbus_object->get_property() tries to invoke a org.freedesktop.DBus.Properties.Get and fails to compile because of the missing ==operator implementation. (Something it needs for casting the specific ValueType, I guess)
dbus_object->get_all_properties() invokes org.freedesktop.DBus.Properties.GetAll which does not need a specific ValueType, so it works.
Of course this is just a workaround to getting properties, since setting a property value is bound to the same shared_pointer as getting it.
As the documentation for fi.w1.wpa_supplicant1.Network.Properties.Properties says:
[...] All values are string type, e.g., frequency is "2437", not 2437.
So try to define DBusDict as follow:
using DBusDict = std::map<std::string, std::string>;

Inheriting std::stack causes an error with clang but works with gcc

Irrelevant. See update below.
I've been playing around with std::stack and noticed something strange. Here's the code:
.h file
template<typename Tp> using VecOfRef = std::vector<std::reference_wrapper<Tp>>;
template <typename T>
struct Stack : public std::stack<T,VecOfRef<T>> {};
struct Simple {
std::string txt = "txt";
};
.cpp file
int main () {
Simple smpl;
auto vec = VecOfRef<Simple>{std::ref(smpl)};
auto stdStack = std::stack<Simple,decltype(vec)>(vec); //works fine
auto myStack = Stack<Simple>(vec); //error
//to check if a reference is stored
stdStack.push(smpl);
smpl.txt.append("append");
Simple& r = sStack.top();
cout << r.txt << endl;
return 0;
}
The error message says:
19:
No matching conversion for functional-style cast from
'std::__1::vector,
std::__1::allocator > >' to
'Stack'
UPDATE:
I have been playing around with this and managed to almost get the code to work:
#include <vector>
#include <string>
#include <stack>
#include <iostream>
#include <functional>
template<typename Tp> using VecOfRef = std::vector<std::reference_wrapper<Tp>>;
template <typename T>
class Stack : public std::stack<T,VecOfRef<T>> {
public:
using std::stack<T,VecOfRef<T>>::stack;
using std::stack<T,VecOfRef<T>>::c;
T& top() {
return c.back().get();
}
};
struct Simple {
std::string txt = "txt";
void print() { std::cout << txt << std::endl; }
};
int main() {
Simple smpl;
Simple smpl_2;
Simple smpl_3;
VecOfRef<Simple> vr {smpl,smpl_2,smpl_3};
// auto myStack = Stack<Simple> (vr); // error
auto myStack = Stack<Simple> ({smpl,smpl_2,smpl_3}); // ok
auto stk = std::stack<Simple,std::vector<std::reference_wrapper<Simple>>>(vr); // ok_2
smpl.txt.append("_append");
smpl_2.txt.append("_append_2");
smpl_3.txt.append("_append_3");
myStack.top().print(); // txt_append_3
myStack.pop();
myStack.top().print(); // txt_append_2
myStack.pop();
myStack.top().print(); // txt_append
return 0;
}
It compiles under gcc but does not under clang. The error says:
Error: stack:154:43: No type named 'type' in 'std::__1::enable_if'; 'enable_if' cannot be used to disable this declaration
Line in the stack file:
Maybe the reason is that you missed a constructor
template <typename T>
struct Stack : public std::stack<T,VecOfRef<T>>
{
Stack(VecOfRef<T>){}
};
You didn't add any constructors to your Stack class.
If you want to inherit std:stack's constructors, you must specify that, using:
using std::stack<T,VecOfRef<T>>::stack; in your class.

C++ expected primary-expression compile error

#include <boost/format.hpp>
#include <boost/scoped_ptr.hpp>
#include <stdexcept>
#include <unordered_map>
#include <functional>
#define DECLARE_OBJECT(classname) namespace {core::declare_object<classname> __declarartion_#classname;}
namespace core {
class dungeon;
class object;
typedef std::function<object* (dungeon *)> object_creator;
namespace library_type {
enum type {
landscape = 0, walker, foe, bonus,object = 42
};
};
struct library_error : public std::logic_error
{
explicit library_error(const std::string &what) : std::logic_error(what) {};
};
template <enum library_type::type type>
class library {
public:
static library<type> *instance() {
if (!m_instance)
m_instance = new library<type>();
return m_instance;
}
template<typename T>
void add_object() {
boost::scoped_ptr<T> obj(T::create(nullptr));
m_library.insert(obj->name(), T::create);
}
const object_creator& get_object(const std::string &key) {
auto lookup_iterator = m_library.find(key);
if (lookup_iterator == m_library.end())
throw library_error(boost::format("Object creator for key `%1%' not found\n") % key);
return *lookup_iterator;
}
private:
library () {};
static library<type> *m_instance;
std::unordered_map<std::string, object_creator> m_library;
};
template <enum library_type::type type>
library<type>* library<type>::m_instance;
template <enum library_type::type type, typename T>
struct declare_object
{
declare_object() {
auto instance = library<type>::instance();
auto method = instance->add_object<T>;
method();
}
};
};
int main()
{
}
Hello. This simple C++0x code gives me error in declare_object constructor
example.cpp: In constructor ‘core::declare_object<type, T>::declare_object()’:
example.cpp:52:43: error: expected primary-expression before ‘>’ token
example.cpp:52:44: error: expected primary-expression before ‘;’ token
I have really no idea where I am wrong. Maybe clear view and suggestions?
Sorry for long listing.
EDIT: Answer was auto method = instance -> template add_object<T>;. Why you deleted your answer?
To get a pointer to member function you need to follow the syntax in the other answer.
Since the member function is furthermore a template, you need to indicate this because it’s a dependent name:
auto method = &library_type<type>::template add_object<T>;
Otherwise C++ will parse the pointy braces in add_object<T> as less-than and greater-than operators.
struct declare_object
{
declare_object() {
auto instance = library<type>::instance();
auto method = &library<type>::template add_object<T>;
(instance->*method)();
}
};

Storing function pointer in std::function

I'm trying to write a C++0x wrapper around dlopen()/dlsym() to dynamically load functions from shared objects:
class DynamicLoader
{
public:
DynamicLoader(std::string const& filename);
template<class Signature>
std::function<Signature> load(std::string const& functionName);
private:
void *itsLibraryHandle;
};
DynamicLoader::DynamicLoader(std::string const& filename)
{
itsLibraryHandle = dlopen(filename.c_str(), RTLD_LAZY);
if(!itsLibraryHandle)
{ /* Throw Some Error */ }
}
template<class Signature>
std::function<Signature> DynamicLoader::load(std::string const& functionName)
{
return <insert magic here> dlsym(itsHandle, functionName.c_str());
}
Is there a way to convert the void* function pointer returned by dlsym into a std::function?
try this:
static_cast<Signature*>()
seems works in VC10
complete test:
#include <functional>
void test()
{}
template <typename Signature>
std::function<Signature> cast(void* f)
{
return static_cast<Signature*>(f);
}
int main()
{
std::function<void()> f = cast<void()>(&test);
return 0;
}
Based on what I see here: http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_pointer.hpp>
template< typename Signature >
std::function<Signature> DynamicLoader::load(std::string const& name)
{
namespace ft = boost::function_types;
typedef typename ft::function_pointer< typename ft::components<Signature>::type >::type fp_t;
fp_t fun_ptr;
*reinterpret_cast<void**>(&fun_ptr) = dlsym(itsHandle, name.c_str());
return fun_ptr;
}
I've never used dlsym so I don't understand why the cast is being done that way and not simply casting dlsym's return like so:
fun_ptr = reinterpret_cast<fp_t>(dlsym(itsHandle, name.c_str());
You just need to cast result of dlsym() call to a proper type. Here's a complete working example:
#include <functional>
#include <iostream>
#include <stdexcept>
#include <string>
#include <dlfcn.h>
class DynamicLoader
{
public:
DynamicLoader(std::string const& filename) :
m_handle(dlopen(filename.c_str(), RTLD_LAZY))
{
if (!m_handle)
{
throw std::logic_error("can't load library named \"" + filename + "\"");
}
}
template<class T>
std::function<T> load(std::string const& functionName) const
{
dlerror();
void* const result = dlsym(m_handle, functionName.c_str());
if (!result)
{
char* const error = dlerror();
if (error)
{
throw std::logic_error("can't find symbol named \"" + functionName + "\": " + error);
}
}
return reinterpret_cast<T*>(result);
}
private:
void* const m_handle;
};
int main()
{
DynamicLoader const loader("/lib64/libz.so.1");
auto const zlibVersion = loader.load<char const* (void)>("zlibVersion");
std::cout << "zlib version: " << zlibVersion() << std::endl;
return 0;
}