diff --git a/include/xo/expression/Apply.hpp b/include/xo/expression/Apply.hpp index f06b8b8b..e95dd76a 100644 --- a/include/xo/expression/Apply.hpp +++ b/include/xo/expression/Apply.hpp @@ -28,6 +28,19 @@ namespace xo { static rp make(const rp & fn, const std::vector> & argv); + /** create apply-expression to add two 64-bit floating-point numbers **/ + static rp make_add2_f64(const rp & lhs, + const rp & rhs); + /** create apply-expression to subtract two 64-bit floating-point numbers **/ + static rp make_sub2_f64(const rp & lhs, + const rp & rhs); + /** create apply-expression to multiply two 64-bit floating-point numbers **/ + static rp make_mul2_f64(const rp & lhs, + const rp & rhs); + /** create apply-expression to divide two 64-bit floating-point numbers **/ + static rp make_div2_f64(const rp & lhs, + const rp & rhs); + /** downcast from Expression **/ static ref::brw from(ref::brw x) { return ref::brw::from(x); diff --git a/include/xo/expression/Primitive.hpp b/include/xo/expression/Primitive.hpp index 5b1d46ac..2305bfe4 100644 --- a/include/xo/expression/Primitive.hpp +++ b/include/xo/expression/Primitive.hpp @@ -10,6 +10,13 @@ #include "xo/reflect/Reflect.hpp" //#include +extern "C" { + /* these symbols needed to link primitives */ + + /* see Primitive_f64::make() */ + double add2_f64(double x, double y); +}; + namespace xo { namespace ast { /** @class Primitive @@ -35,6 +42,7 @@ namespace xo { using Reflect = xo::reflect::Reflect; using TaggedPtr = xo::reflect::TaggedPtr; using TypeDescr = xo::reflect::TypeDescr; + using fptr_type = FunctionPointer; public: static rp make(const std::string & name, @@ -46,8 +54,9 @@ namespace xo { return new Primitive(fn_type, name, fnptr, explicit_symbol_def, intrinsic); } + /** see classes below for intrinsics **/ + FunctionPointer value() const { return value_; } - llvmintrinsic intrinsic() const { return intrinsic_; } TypeDescr value_td() const { return value_td_; } TaggedPtr value_tp() const { @@ -60,6 +69,7 @@ namespace xo { // ----- PrimitiveInterface ----- + virtual llvmintrinsic intrinsic() const override { return intrinsic_; } virtual bool explicit_symbol_def() const override { return explicit_symbol_def_; } virtual void_function_type function_address() const override { return reinterpret_cast(value_); } @@ -113,7 +123,7 @@ namespace xo { /** for LLVM: if true, use Jit.intern_symbol() to provide explicit binding. * * Not obvious what distinguishes functions like ::sin(), ::sqrt() - * (which work without this) from symbols like ::mul_i32(), which do. + * (which work without this) from symbols like ::mul_i32(), which require it. **/ bool explicit_symbol_def_ = false; /** invalid: generate call (IRBuilder::CreateCall) @@ -132,6 +142,21 @@ namespace xo { { return Primitive::make(name, x, explicit_symbol_def, intrinsic); } + + class Primitive_f64 : public Primitive { + public: + using PrimitiveType = Primitive; + + public: + /** add2_f64: add two 64-bit floating-point numbers **/ + static rp make_add2_f64(); + /** sub2_f64: subtract two 64-bit floating-point numbers **/ + static rp make_sub2_f64(); + /** mul2_f64: multiply two 64-bit floating-point numbers **/ + static rp make_mul2_f64(); + /** div2_f64: divide two 64-bit floating-point numbers **/ + static rp make_div2_f64(); + }; } /*namespace ast*/ } /*namespace xo*/ diff --git a/include/xo/expression/llvmintrinsic.hpp b/include/xo/expression/llvmintrinsic.hpp index 052baa9e..bc484640 100644 --- a/include/xo/expression/llvmintrinsic.hpp +++ b/include/xo/expression/llvmintrinsic.hpp @@ -65,6 +65,9 @@ namespace xo { /** -> IRBuilder::CreateFadd (add 2 floating-point numbers) **/ fp_add, + /** -> IRBuilder::CreateFsub (subtract 2 floating-pointer numbers) **/ + fp_sub, + /** -> IRBuilder::CreateFmul (multiply 2 floating-point numbers) **/ fp_mul, @@ -105,6 +108,7 @@ namespace xo { case llvmintrinsic::i_sdiv: return "i_sdiv"; case llvmintrinsic::i_udiv: return "i_udiv"; case llvmintrinsic::fp_add: return "fp_add"; + case llvmintrinsic::fp_sub: return "fp_sub"; case llvmintrinsic::fp_mul: return "fp_mul"; case llvmintrinsic::fp_div: return "fp_div"; case llvmintrinsic::fp_sqrt: return "fp_sqrt"; diff --git a/src/expression/Apply.cpp b/src/expression/Apply.cpp index 36e2428a..497565b1 100644 --- a/src/expression/Apply.cpp +++ b/src/expression/Apply.cpp @@ -1,6 +1,7 @@ /* @file Apply.cpp */ #include "Apply.hpp" +#include "Primitive.hpp" #include "xo/indentlog/print/vector.hpp" namespace xo { @@ -25,6 +26,38 @@ namespace xo { return new Apply(fn_retval_type, fn, argv); } + rp + Apply::make_add2_f64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_f64::make_add2_f64(), + {lhs, rhs}); + } + + rp + Apply::make_sub2_f64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_f64::make_sub2_f64(), + {lhs, rhs}); + } + + rp + Apply::make_mul2_f64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_f64::make_mul2_f64(), + {lhs, rhs}); + } + + rp + Apply::make_div2_f64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_f64::make_div2_f64(), + {lhs, rhs}); + } + void Apply::display(std::ostream & os) const { os << " rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("add2_f64", + &add2_f64, + true /*explicit_symbol_def*/, + llvmintrinsic::fp_add); + + return s_retval; + } + + auto + Primitive_f64::make_sub2_f64() -> rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("sub2_f64", + &sub2_f64, + true /*explicit_symbol_def*/, + llvmintrinsic::fp_sub); + + return s_retval; + } + + auto + Primitive_f64::make_mul2_f64() -> rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("mul2_f64", + &mul2_f64, + true /*explicit_symbol_def*/, + llvmintrinsic::fp_mul); + + return s_retval; + } + + auto + Primitive_f64::make_div2_f64() -> rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("div2_f64", + &div2_f64, + true /*explicit_symbol_def*/, + llvmintrinsic::fp_div); + + return s_retval; + } + + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end Primitive.cpp */ diff --git a/src/expression/intrinsics.cpp b/src/expression/intrinsics.cpp new file mode 100644 index 00000000..27dcd83a --- /dev/null +++ b/src/expression/intrinsics.cpp @@ -0,0 +1,14 @@ +/* @file intrinsics.cpp */ + +#include "intrinsics.hpp" + +/* FIXME: don't know how to mangle symbols yet, + * so putting functions invoked from jit into global namespace + */ +extern "C" +int32_t +mul_i32(int32_t x, int32_t y) { + return x * y; +} + +/* end intrinsics.cpp */