xo-expression: + Primitive::intrinsic

This commit is contained in:
Roland Conybeare 2024-06-21 14:05:49 -04:00
commit 4d486c0e5c
3 changed files with 34 additions and 15 deletions

View file

@ -2,6 +2,7 @@
#include "xo/expression/Constant.hpp"
#include "xo/expression/Primitive.hpp"
#include "xo/expression/llvmintrinsic.hpp"
#include <iostream>
#include <cmath>
@ -9,6 +10,7 @@ int
main() {
using xo::ast::make_constant;
using xo::ast::make_primitive;
using xo::ast::llvmintrinsic;
using std::cout;
using std::endl;
@ -19,7 +21,8 @@ main() {
{
auto expr = make_primitive("sqrt",
&::sqrt,
false /*!explicit_symbol_def*/);
false /*!explicit_symbol_def*/,
llvmintrinsic::fp_sqrt);
auto expr_td = expr->value_td();

View file

@ -6,6 +6,7 @@
#pragma once
#include "PrimitiveInterface.hpp"
#include "llvmintrinsic.hpp"
#include "xo/reflect/Reflect.hpp"
//#include <cstdint>
@ -15,9 +16,11 @@ namespace xo {
* @brief syntax for a constant that refers to a known function.
*
* Two cases here:
* 1. primitive refers to a function that is supported directly in llvm
* (e.g. floating-point addition)
* 2. primitive refers to a compiled (C/C++) function that we can invoke at runtime
* 1. (always) primitive refers to a compiled (C/C++) function that we can invoke at runtime
* 2. (sometimes) primitive also refers to a function that is supported directly in llvm
* (e.g. floating-point addition). In that case @ref intrinsic_
* identifies that direct support, provided it knows at codegen time which primitive
* is being invoked
*
* In any case, a primitive serves as both declaration and definition
* (May be possible to relax this to declaration-only using null value_ as sentinel..?)
@ -36,13 +39,15 @@ namespace xo {
public:
static ref::rp<Primitive> make(const std::string & name,
FunctionPointer fnptr,
bool explicit_symbol_def) {
bool explicit_symbol_def,
llvmintrinsic intrinsic) {
TypeDescr fn_type = Reflect::require<FunctionPointer>();
return new Primitive(fn_type, name, fnptr, explicit_symbol_def);
return new Primitive(fn_type, name, fnptr, explicit_symbol_def, intrinsic);
}
FunctionPointer value() const { return value_; }
llvmintrinsic intrinsic() const { return intrinsic_; }
TypeDescr value_td() const { return value_td_; }
TaggedPtr value_tp() const {
@ -79,12 +84,14 @@ namespace xo {
Primitive(TypeDescr fn_type,
const std::string & name,
FunctionPointer fnptr,
bool explicit_symbol_def)
bool explicit_symbol_def,
llvmintrinsic intrinsic)
: PrimitiveInterface(fn_type),
name_{name},
value_td_{Reflect::require_function<FunctionPointer>()},
value_{fnptr},
explicit_symbol_def_{explicit_symbol_def}
explicit_symbol_def_{explicit_symbol_def},
intrinsic_{intrinsic}
{
if (!value_td_->is_function())
throw std::runtime_error("Primitive: expected function pointer");
@ -103,11 +110,16 @@ 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)
/** 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.
**/
bool explicit_symbol_def_ = false;
/** invalid: generate call (IRBuilder::CreateCall)
* all others: generate direct use of LLVM intrinsic
**/
llvmintrinsic intrinsic_;
}; /*Primitive*/
/** adopt function @p x as a callable primitive function named @p name **/
@ -115,9 +127,10 @@ namespace xo {
ref::rp<Primitive<FunctionPointer>>
make_primitive(const std::string & name,
FunctionPointer x,
bool explicit_symbol_def)
bool explicit_symbol_def,
llvmintrinsic intrinsic)
{
return Primitive<FunctionPointer>::make(name, x, explicit_symbol_def);
return Primitive<FunctionPointer>::make(name, x, explicit_symbol_def, intrinsic);
}
} /*namespace ast*/
} /*namespace xo*/

View file

@ -6,6 +6,7 @@
#pragma once
#include "FunctionInterface.hpp"
#include "llvmintrinsic.hpp"
//#include <cstdint>
@ -34,10 +35,12 @@ namespace xo {
**/
virtual bool explicit_symbol_def() const = 0;
/** function address for this primitive
**/
/** function address for this primitive **/
virtual void_function_type function_address() const = 0;
/** get llvm intrinsic hint for this primitive **/
virtual llvmintrinsic intrinsic() const = 0;
// virtual const std::string & name() const;
// virtual int n_arg() const;
// virtual TypeDescr fn_retval() const;