diff --git a/example/ex1/ex1.cpp b/example/ex1/ex1.cpp index 5c12a4b1..be606918 100644 --- a/example/ex1/ex1.cpp +++ b/example/ex1/ex1.cpp @@ -17,7 +17,9 @@ main() { } { - auto expr = make_primitive("sqrt", &::sqrt); + auto expr = make_primitive("sqrt", + &::sqrt, + false /*!explicit_symbol_def*/); auto expr_td = expr->value_td(); diff --git a/include/xo/expression/Primitive.hpp b/include/xo/expression/Primitive.hpp index f251465d..caf7f1bf 100644 --- a/include/xo/expression/Primitive.hpp +++ b/include/xo/expression/Primitive.hpp @@ -35,10 +35,11 @@ namespace xo { public: static ref::rp make(const std::string & name, - FunctionPointer fnptr) { + FunctionPointer fnptr, + bool explicit_symbol_def) { TypeDescr fn_type = Reflect::require(); - return new Primitive(fn_type, name, fnptr); + return new Primitive(fn_type, name, fnptr, explicit_symbol_def); } FunctionPointer value() const { return value_; } @@ -54,6 +55,9 @@ namespace xo { // ----- PrimitiveInterface ----- + virtual bool explicit_symbol_def() const override { return explicit_symbol_def_; } + virtual void_function_type function_address() const override { return reinterpret_cast(value_); } + // ----- FunctionInterface ----- virtual std::string const & name() const override { return name_; } @@ -74,11 +78,13 @@ namespace xo { private: Primitive(TypeDescr fn_type, const std::string & name, - FunctionPointer fnptr) + FunctionPointer fnptr, + bool explicit_symbol_def) : PrimitiveInterface(fn_type), name_{name}, value_td_{Reflect::require_function()}, - value_{fnptr} + value_{fnptr}, + explicit_symbol_def_{explicit_symbol_def} { if (!value_td_->is_function()) throw std::runtime_error("Primitive: expected function pointer"); @@ -97,13 +103,21 @@ namespace xo { TypeDescr value_td_; /** address of executable function **/ FunctionPointer value_; + /** if true, use Jit.intern_symbol() to provide explicit binding. + * Currently mystified as to what's distinguishes functions like ::sin(), ::sqrt() + * (which work do not require this) from symbols like ::mul_i32(), which do) + **/ + bool explicit_symbol_def_ = false; }; /*Primitive*/ /** adopt function @p x as a callable primitive function named @p name **/ template ref::rp> - make_primitive(const std::string & name, FunctionPointer x) { - return Primitive::make(name, x); + make_primitive(const std::string & name, + FunctionPointer x, + bool explicit_symbol_def) + { + return Primitive::make(name, x, explicit_symbol_def); } } /*namespace ast*/ } /*namespace xo*/ diff --git a/include/xo/expression/PrimitiveInterface.hpp b/include/xo/expression/PrimitiveInterface.hpp index 685d04ae..0b42b252 100644 --- a/include/xo/expression/PrimitiveInterface.hpp +++ b/include/xo/expression/PrimitiveInterface.hpp @@ -13,6 +13,9 @@ namespace xo { namespace ast { class PrimitiveInterface : public FunctionInterface { + public: + using void_function_type = void (*)(); + public: PrimitiveInterface(TypeDescr fn_type) : FunctionInterface(exprtype::primitive, fn_type) {} @@ -22,6 +25,19 @@ namespace xo { return ref::brw::from(x); } + /** if true, Jit will try to explicitly symbol for this primitive + * (instead of looking it up in host process). + * Don't know if this works. + * Do know it's not needed for ::sin(), ::sqrt(). + * Do know that my extern "C" functions like ::mul_i32(), ::mul_f64() + * need something else. + **/ + virtual bool explicit_symbol_def() const = 0; + + /** function address for this primitive + **/ + virtual void_function_type function_address() const = 0; + // virtual const std::string & name() const; // virtual int n_arg() const; // virtual TypeDescr fn_retval() const;