xo-expression: arithmetic expression support
This commit is contained in:
parent
fce0fea1cb
commit
d4fd55b8ed
7 changed files with 181 additions and 2 deletions
|
|
@ -28,6 +28,19 @@ namespace xo {
|
||||||
static rp<Apply> make(const rp<Expression> & fn,
|
static rp<Apply> make(const rp<Expression> & fn,
|
||||||
const std::vector<rp<Expression>> & argv);
|
const std::vector<rp<Expression>> & argv);
|
||||||
|
|
||||||
|
/** create apply-expression to add two 64-bit floating-point numbers **/
|
||||||
|
static rp<Apply> make_add2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs);
|
||||||
|
/** create apply-expression to subtract two 64-bit floating-point numbers **/
|
||||||
|
static rp<Apply> make_sub2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs);
|
||||||
|
/** create apply-expression to multiply two 64-bit floating-point numbers **/
|
||||||
|
static rp<Apply> make_mul2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs);
|
||||||
|
/** create apply-expression to divide two 64-bit floating-point numbers **/
|
||||||
|
static rp<Apply> make_div2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs);
|
||||||
|
|
||||||
/** downcast from Expression **/
|
/** downcast from Expression **/
|
||||||
static ref::brw<Apply> from(ref::brw<Expression> x) {
|
static ref::brw<Apply> from(ref::brw<Expression> x) {
|
||||||
return ref::brw<Apply>::from(x);
|
return ref::brw<Apply>::from(x);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,13 @@
|
||||||
#include "xo/reflect/Reflect.hpp"
|
#include "xo/reflect/Reflect.hpp"
|
||||||
//#include <cstdint>
|
//#include <cstdint>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
/* these symbols needed to link primitives */
|
||||||
|
|
||||||
|
/* see Primitive_f64::make() */
|
||||||
|
double add2_f64(double x, double y);
|
||||||
|
};
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
/** @class Primitive
|
/** @class Primitive
|
||||||
|
|
@ -35,6 +42,7 @@ namespace xo {
|
||||||
using Reflect = xo::reflect::Reflect;
|
using Reflect = xo::reflect::Reflect;
|
||||||
using TaggedPtr = xo::reflect::TaggedPtr;
|
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||||
using TypeDescr = xo::reflect::TypeDescr;
|
using TypeDescr = xo::reflect::TypeDescr;
|
||||||
|
using fptr_type = FunctionPointer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static rp<Primitive> make(const std::string & name,
|
static rp<Primitive> make(const std::string & name,
|
||||||
|
|
@ -46,8 +54,9 @@ namespace xo {
|
||||||
return new Primitive(fn_type, name, fnptr, explicit_symbol_def, intrinsic);
|
return new Primitive(fn_type, name, fnptr, explicit_symbol_def, intrinsic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** see classes below for intrinsics **/
|
||||||
|
|
||||||
FunctionPointer value() const { return value_; }
|
FunctionPointer value() const { return value_; }
|
||||||
llvmintrinsic intrinsic() const { return intrinsic_; }
|
|
||||||
|
|
||||||
TypeDescr value_td() const { return value_td_; }
|
TypeDescr value_td() const { return value_td_; }
|
||||||
TaggedPtr value_tp() const {
|
TaggedPtr value_tp() const {
|
||||||
|
|
@ -60,6 +69,7 @@ namespace xo {
|
||||||
|
|
||||||
// ----- PrimitiveInterface -----
|
// ----- PrimitiveInterface -----
|
||||||
|
|
||||||
|
virtual llvmintrinsic intrinsic() const override { return intrinsic_; }
|
||||||
virtual bool explicit_symbol_def() const override { return explicit_symbol_def_; }
|
virtual bool explicit_symbol_def() const override { return explicit_symbol_def_; }
|
||||||
virtual void_function_type function_address() const override { return reinterpret_cast<void_function_type>(value_); }
|
virtual void_function_type function_address() const override { return reinterpret_cast<void_function_type>(value_); }
|
||||||
|
|
||||||
|
|
@ -113,7 +123,7 @@ namespace xo {
|
||||||
/** for LLVM: if true, use Jit.intern_symbol() to provide explicit binding.
|
/** for LLVM: if true, use Jit.intern_symbol() to provide explicit binding.
|
||||||
*
|
*
|
||||||
* Not obvious what distinguishes functions like ::sin(), ::sqrt()
|
* 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;
|
bool explicit_symbol_def_ = false;
|
||||||
/** invalid: generate call (IRBuilder::CreateCall)
|
/** invalid: generate call (IRBuilder::CreateCall)
|
||||||
|
|
@ -132,6 +142,21 @@ namespace xo {
|
||||||
{
|
{
|
||||||
return Primitive<FunctionPointer>::make(name, x, explicit_symbol_def, intrinsic);
|
return Primitive<FunctionPointer>::make(name, x, explicit_symbol_def, intrinsic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Primitive_f64 : public Primitive<double (*)(double, double)> {
|
||||||
|
public:
|
||||||
|
using PrimitiveType = Primitive<double (*)(double, double)>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** add2_f64: add two 64-bit floating-point numbers **/
|
||||||
|
static rp<PrimitiveType> make_add2_f64();
|
||||||
|
/** sub2_f64: subtract two 64-bit floating-point numbers **/
|
||||||
|
static rp<PrimitiveType> make_sub2_f64();
|
||||||
|
/** mul2_f64: multiply two 64-bit floating-point numbers **/
|
||||||
|
static rp<PrimitiveType> make_mul2_f64();
|
||||||
|
/** div2_f64: divide two 64-bit floating-point numbers **/
|
||||||
|
static rp<PrimitiveType> make_div2_f64();
|
||||||
|
};
|
||||||
} /*namespace ast*/
|
} /*namespace ast*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,9 @@ namespace xo {
|
||||||
/** -> IRBuilder::CreateFadd (add 2 floating-point numbers) **/
|
/** -> IRBuilder::CreateFadd (add 2 floating-point numbers) **/
|
||||||
fp_add,
|
fp_add,
|
||||||
|
|
||||||
|
/** -> IRBuilder::CreateFsub (subtract 2 floating-pointer numbers) **/
|
||||||
|
fp_sub,
|
||||||
|
|
||||||
/** -> IRBuilder::CreateFmul (multiply 2 floating-point numbers) **/
|
/** -> IRBuilder::CreateFmul (multiply 2 floating-point numbers) **/
|
||||||
fp_mul,
|
fp_mul,
|
||||||
|
|
||||||
|
|
@ -105,6 +108,7 @@ namespace xo {
|
||||||
case llvmintrinsic::i_sdiv: return "i_sdiv";
|
case llvmintrinsic::i_sdiv: return "i_sdiv";
|
||||||
case llvmintrinsic::i_udiv: return "i_udiv";
|
case llvmintrinsic::i_udiv: return "i_udiv";
|
||||||
case llvmintrinsic::fp_add: return "fp_add";
|
case llvmintrinsic::fp_add: return "fp_add";
|
||||||
|
case llvmintrinsic::fp_sub: return "fp_sub";
|
||||||
case llvmintrinsic::fp_mul: return "fp_mul";
|
case llvmintrinsic::fp_mul: return "fp_mul";
|
||||||
case llvmintrinsic::fp_div: return "fp_div";
|
case llvmintrinsic::fp_div: return "fp_div";
|
||||||
case llvmintrinsic::fp_sqrt: return "fp_sqrt";
|
case llvmintrinsic::fp_sqrt: return "fp_sqrt";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
/* @file Apply.cpp */
|
/* @file Apply.cpp */
|
||||||
|
|
||||||
#include "Apply.hpp"
|
#include "Apply.hpp"
|
||||||
|
#include "Primitive.hpp"
|
||||||
#include "xo/indentlog/print/vector.hpp"
|
#include "xo/indentlog/print/vector.hpp"
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
|
@ -25,6 +26,38 @@ namespace xo {
|
||||||
return new Apply(fn_retval_type, fn, argv);
|
return new Apply(fn_retval_type, fn, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rp<Apply>
|
||||||
|
Apply::make_add2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs)
|
||||||
|
{
|
||||||
|
return Apply::make(Primitive_f64::make_add2_f64(),
|
||||||
|
{lhs, rhs});
|
||||||
|
}
|
||||||
|
|
||||||
|
rp<Apply>
|
||||||
|
Apply::make_sub2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs)
|
||||||
|
{
|
||||||
|
return Apply::make(Primitive_f64::make_sub2_f64(),
|
||||||
|
{lhs, rhs});
|
||||||
|
}
|
||||||
|
|
||||||
|
rp<Apply>
|
||||||
|
Apply::make_mul2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs)
|
||||||
|
{
|
||||||
|
return Apply::make(Primitive_f64::make_mul2_f64(),
|
||||||
|
{lhs, rhs});
|
||||||
|
}
|
||||||
|
|
||||||
|
rp<Apply>
|
||||||
|
Apply::make_div2_f64(const rp<Expression> & lhs,
|
||||||
|
const rp<Expression> & rhs)
|
||||||
|
{
|
||||||
|
return Apply::make(Primitive_f64::make_div2_f64(),
|
||||||
|
{lhs, rhs});
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Apply::display(std::ostream & os) const {
|
Apply::display(std::ostream & os) const {
|
||||||
os << "<Apply"
|
os << "<Apply"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ set(SELF_SRCS
|
||||||
IfExpr.cpp
|
IfExpr.cpp
|
||||||
LocalEnv.cpp
|
LocalEnv.cpp
|
||||||
ConvertExpr.cpp
|
ConvertExpr.cpp
|
||||||
|
Primitive.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||||
|
|
|
||||||
89
src/expression/Primitive.cpp
Normal file
89
src/expression/Primitive.cpp
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
/* @file Primitive.cpp */
|
||||||
|
|
||||||
|
#include "Primitive.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
double
|
||||||
|
add2_f64(double x, double y) {
|
||||||
|
return x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
sub2_f64(double x, double y) {
|
||||||
|
return x - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
mul2_f64(double x, double y) {
|
||||||
|
return x * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
div2_f64(double x, double y) {
|
||||||
|
return x / y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace ast {
|
||||||
|
auto
|
||||||
|
Primitive_f64::make_add2_f64() -> rp<PrimitiveType>
|
||||||
|
{
|
||||||
|
static rp<PrimitiveType> 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<PrimitiveType>
|
||||||
|
{
|
||||||
|
static rp<PrimitiveType> 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<PrimitiveType>
|
||||||
|
{
|
||||||
|
static rp<PrimitiveType> 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<PrimitiveType>
|
||||||
|
{
|
||||||
|
static rp<PrimitiveType> 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 */
|
||||||
14
src/expression/intrinsics.cpp
Normal file
14
src/expression/intrinsics.cpp
Normal file
|
|
@ -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 */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue