Skip to content

Commit

Permalink
Merge branch 'main' into simplify_val
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippGrulich authored Jul 31, 2024
2 parents 5eea0cd + f512110 commit 0f81c3a
Show file tree
Hide file tree
Showing 87 changed files with 2,288 additions and 838 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ AccessModifierOffset: -4
AllowShortFunctionsOnASingleLine: false
AllowShortLambdasOnASingleLine: Inline
AlwaysBreakTemplateDeclarations: Yes
ColumnLimit: 120
ColumnLimit: 240
CompactNamespaces: true
IncludeBlocks: Merge
IncludeCategories:
Expand Down
11 changes: 11 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"image": "mcr.microsoft.com/devcontainers/cpp:ubuntu-24.04",
"name": "Try Nautilus",
"customizations": {
"vscode": {
"extensions": [
"matepek.vscode-catch2-test-adapter"
]
}
}
}
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ jobs:
- name: test
shell: bash
run: |
cd nautilus && ctest --test-dir=nautilus --output-on-failure
ctest --test-dir nautilus --output-on-failure
82 changes: 63 additions & 19 deletions nautilus/include/nautilus/Engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "nautilus/config.hpp"
#include "nautilus/core.hpp"
#include "nautilus/options.hpp"
#include <functional>

namespace nautilus::engine {

Expand Down Expand Up @@ -55,40 +56,61 @@ template <typename R, typename... FunctionArguments>
std::function<void()> createFunctionWrapper(R (*fnptr)(FunctionArguments...)) {
return createFunctionWrapper(std::make_index_sequence<sizeof...(FunctionArguments)> {}, fnptr);
}

template <size_t... Indices, typename R, typename... FunctionArguments>
std::function<void()> createFunctionWrapper(std::index_sequence<Indices...>, std::function<R(FunctionArguments...)> func) {
[[maybe_unused]] std::size_t args = sizeof...(FunctionArguments);
auto traceFunc = [=]() {
if constexpr (std::is_void_v<R>) {
func(details::createTraceArgument<FunctionArguments, Indices>()...);
tracing::traceReturnOperation(Type::v, tracing::value_ref());
} else {
auto returnValue = func(details::createTraceArgument<FunctionArguments, Indices>()...);
auto type = tracing::to_type<typename decltype(returnValue)::basic_type>();
tracing::traceReturnOperation(type, returnValue.state);
}
};
return traceFunc;
}

template <typename R, typename... FunctionArguments>
std::function<void()> createFunctionWrapper(std::function<R(FunctionArguments...)> func) {
return createFunctionWrapper(std::make_index_sequence<sizeof...(FunctionArguments)> {}, func);
}
#endif
} // namespace details

template <typename R, typename... FunctionArguments>
class CallableFunction {
public:
explicit CallableFunction(void* func) : func(func), executable(nullptr) {
explicit CallableFunction(std::function<R(FunctionArguments...)> func) : func(func), executable(nullptr) {
}

explicit CallableFunction(std::unique_ptr<compiler::Executable>& executable)
: func(), executable(std::move(executable)) {
if (this->executable->hasInvocableFunctionPtr()) {
func = this->executable->getInvocableFunctionPtr("execute");
}
}
: func(), executable(std::move(executable)) {}

template <typename... FunctionArgumentsRaw>
requires std::is_void_v<R>
auto operator()(FunctionArgumentsRaw... args) {
// function is called from an external context.
using FunctionType = void(FunctionArguments...);
auto fnptr = reinterpret_cast<FunctionType*>(func);
fnptr(details::transform((args))...);
// no executable is defined, call the underling function directly and convert all arguments to val objects
if (executable == nullptr) {
func(details::transform((args))...);
return;
}
auto callable =
this->executable->template getInvocableMember<void, FunctionArgumentsRaw...>("execute");
callable(args...);
return;
}

template <typename... FunctionArgumentsRaw>
requires(!std::is_void_v<R>)
auto operator()(FunctionArgumentsRaw... args) {
// function is called from an external context.

// no executable is defined, call the underling function directly and convert all arguments to val objects
if (executable == nullptr) {
using FunctionType = R(FunctionArguments...);
auto fnptr = reinterpret_cast<FunctionType*>(func);
auto result = fnptr(details::transform((args))...);
auto result = func(details::transform((args))...);
return nautilus::details::getRawValue(result);
}
auto callable =
Expand All @@ -97,7 +119,7 @@ class CallableFunction {
}

private:
void* func;
std::function<R(FunctionArguments...)> func;
std::unique_ptr<compiler::Executable> executable;
};

Expand All @@ -117,17 +139,39 @@ class NautilusEngine {
return CallableFunction<val<R>, val<FunctionArguments>...>(executable);
}
#endif
return CallableFunction<val<R>, val<FunctionArguments>...>((void*) fnptr);
std::function<val<R>(val<FunctionArguments>...)> inputWrapper = fnptr;
return CallableFunction<val<R>, val<FunctionArguments>...>(inputWrapper);
}

template <typename... FunctionArguments>
auto registerFunction(void (*fnptr)(FunctionArguments...)) const {
// auto wrapper = createFunctionWrapper(fnptr);
// auto executable = jit->compile(wrapper);
// auto ptr = reinterpret_cast<R (*)(FunctionArguments...)>(executable);
return CallableFunction<void, FunctionArguments...>((void*) fnptr);
#ifdef ENABLE_TRACING
if (options.getOptionOrDefault("engine.Compilation", true)) {
auto wrapper = details::createFunctionWrapper(fnptr);
auto executable = jit.compile(wrapper);
return CallableFunction<void, FunctionArguments...>(executable);
}
#endif
std::function<void(FunctionArguments...)> inputWrapper = fnptr;
return CallableFunction<void, FunctionArguments...>(inputWrapper);
}


template <typename R, typename... FunctionArguments>
auto registerFunction(std::function<R(val<FunctionArguments>...)> func) const {
#ifdef ENABLE_TRACING
if (options.getOptionOrDefault("engine.Compilation", true)) {
auto wrapper = details::createFunctionWrapper(func);
auto executable = jit.compile(wrapper);
return CallableFunction<R, val<FunctionArguments>...>(executable);
}
#endif
return CallableFunction<R, val<FunctionArguments>...>(func);
}




private:
const compiler::JITCompiler jit;
const Options options;
Expand Down
3 changes: 3 additions & 0 deletions nautilus/include/nautilus/Executable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class Executable {
if constexpr (!std::is_void_v<R>) {
std::vector<std::any> inputs_ = {getGenericArg(arguments)...};
auto res = genericFunction->invokeGeneric(inputs_);
if (std::is_same_v<R, char>) {
return std::any_cast<int8_t>(res);
}
return std::any_cast<R>(res);
} else {
std::vector<std::any> inputs_ = {getGenericArg(arguments)...};
Expand Down
6 changes: 4 additions & 2 deletions nautilus/include/nautilus/common/traceing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ enum Op : uint8_t {
LSH,
RSH,
BOR,
BXOR,
BAND,
NEGATE,
};
Expand Down Expand Up @@ -93,7 +94,7 @@ constexpr Type to_type() {
using type = std::remove_cvref_t<T>;
if constexpr (std::is_same_v<type, bool>) {
return Type::b;
} else if constexpr (std::is_same_v<type, int8_t>) {
} else if constexpr (std::is_same_v<type, int8_t> || (std::is_same_v<type, char>)) {
return Type::i8;
} else if constexpr (std::is_same_v<type, int16_t>) {
return Type::i16;
Expand Down Expand Up @@ -162,7 +163,8 @@ value_ref traceCast(value_ref state, Type resultType);

std::array<uint8_t, 256>& getVarRefMap();

value_ref traceCall(const std::string& functionName, void* fptn, Type resultType, std::vector<tracing::value_ref> arguments);
value_ref traceCall(const std::string& functionName, void* fptn, Type resultType,
std::vector<tracing::value_ref> arguments);

std::ostream& operator<<(std::ostream& os, const Op& operation);

Expand Down
1 change: 1 addition & 0 deletions nautilus/include/nautilus/function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class CallableRuntimeFunction {
auto ptr = (void*) fnptr;
auto functionArgumentReferences = getArgumentReferences("functionName", (void*) fnptr, args...);
tracing::traceCall(functionName, ptr, Type::v, functionArgumentReferences);
return;
}
#endif
fnptr(transform((args))...);
Expand Down
12 changes: 7 additions & 5 deletions nautilus/include/nautilus/val.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ template <is_integral LHS, is_integral RHS>
auto shr(val<LHS>& left, val<RHS>& right);

template <is_fundamental LHS>
auto neg(val<LHS>& val);
val<LHS> neg(val<LHS>& val);

template <typename T>
tracing::value_ref getState(T&& value) {
Expand Down Expand Up @@ -425,15 +425,17 @@ DEFINE_BINARY_OPERATOR_HELPER(&, bAnd, BAND, COMMON_RETURN_TYPE)

DEFINE_BINARY_OPERATOR_HELPER(|, bOr, BOR, COMMON_RETURN_TYPE)

DEFINE_BINARY_OPERATOR_HELPER(^, bXOr, BOR, COMMON_RETURN_TYPE)
DEFINE_BINARY_OPERATOR_HELPER(^, bXOr, BXOR, COMMON_RETURN_TYPE)

template <is_fundamental LHS>
val<LHS> inline neg(val<LHS>& val) {
val<LHS> neg(val<LHS>& val) {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = traceUnaryOp<tracing::NEGATE, LHS>(val.state);
return tc;
}
return ~val.value;
#endif
return ~getRawValue(val);
}

template <typename LHS>
Expand Down Expand Up @@ -618,7 +620,7 @@ auto inline operator&&(LHS left, RHS right) {
}

template <typename LHS>
auto inline operator!(LHS left) {
auto inline operator!(val<LHS> left) {
return details::lNot(left);
}

Expand Down
2 changes: 1 addition & 1 deletion nautilus/include/nautilus/val_enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class val<T> {
val(val<T>& t) : state(tracing::traceCopy(t.state)), value(t.value) {};
val(T val) : state(tracing::traceConstant((underlying_type_t) val)), value(val) {};
#else
val(val<underlying_type_t> t) : value((T) t.value) {};
val(val<underlying_type_t> t) : value((T) details::getRawValue(t)) {};
val(val<T>& t) : value(t.value) {};
val(T val) : value(val) {};
#endif
Expand Down
71 changes: 71 additions & 0 deletions nautilus/include/nautilus/val_ptr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ template <is_ptr ValuePtrType>
class val<ValuePtrType> : public base_ptr_val<ValuePtrType> {
public:
using base_ptr_val<ValuePtrType>::base_ptr_val;

// enable cast to type T
template <class T>
operator val<T*>() const {
return val<T*>((T*) this->value, this->state);
}
};

template <is_arithmetic_ptr ValuePtrType>
Expand Down Expand Up @@ -194,39 +200,104 @@ auto inline operator-(val<ValueType> left, std::remove_pointer_t<ValueType> righ
template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator==(val<ValueType> left, val<ValueType> right) {

#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp<tracing::EQ, ValueType>(left.state, right.state);
return val<bool>(tc);
}
#endif
return val<bool>(left.value == right.value);
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator==(val<ValueType> left, std::nullptr_t) {
auto nullVal = val<ValueType>(NULL);
return left == nullVal;
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator==(std::nullptr_t, val<ValueType> right) {
auto nullVal = val<ValueType>(NULL);
return nullVal == right;
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator<=(val<ValueType> left, val<ValueType> right) {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp<tracing::LTE, ValueType>(left.state, right.state);
return val<bool>(tc);
}
#endif
return val<bool>(left.value <= right.value);
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator<(val<ValueType> left, val<ValueType> right) {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp<tracing::LT, ValueType>(left.state, right.state);
return val<bool>(tc);
}
#endif
return val<bool>(left.value < right.value);
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator>(val<ValueType> left, val<ValueType> right) {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp<tracing::GT, ValueType>(left.state, right.state);
return val<bool>(tc);
}
#endif
return val<bool>(left.value > right.value);
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator>=(val<ValueType> left, val<ValueType> right) {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp<tracing::GTE, ValueType>(left.state, right.state);
return val<bool>(tc);
}
#endif
return val<bool>(left.value >= right.value);
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator!=(val<ValueType> left, val<ValueType> right) {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp<tracing::NEQ, ValueType>(left.state, right.state);
return val<bool>(tc);
}
#endif
return val<bool>(left.value != right.value);
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator!=(val<ValueType> left, std::nullptr_t) {
auto nullVal = val<ValueType>(NULL);
return left != nullVal;
}

template <typename ValueType>
requires std::is_pointer_v<ValueType>
auto inline operator!=(std::nullptr_t, val<ValueType> right) {
auto nullVal = val<ValueType>(NULL);
return nullVal != right;
}

template <>
class val<bool&> {
public:
Expand Down
3 changes: 1 addition & 2 deletions nautilus/src/nautilus/compiler/JITCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ namespace nautilus::compiler {
JITCompiler::JITCompiler() : options(), backends(std::make_unique<CompilationBackendRegistry>()) {
}

JITCompiler::JITCompiler(engine::Options options)
: options(std::move(options)), backends(std::make_unique<CompilationBackendRegistry>()) {
JITCompiler::JITCompiler(engine::Options options) : options(std::move(options)), backends(std::make_unique<CompilationBackendRegistry>()) {
}

JITCompiler::~JITCompiler() = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ namespace nautilus::compiler::asmjit {

using namespace ::asmjit;

A64LoweringProvider::LoweringContext::LoweringContext(std::shared_ptr<ir::IRGraph> ir, CodeHolder& code)
: cc(&code), ir(std::move(ir)) {
A64LoweringProvider::LoweringContext::LoweringContext(std::shared_ptr<ir::IRGraph> ir, CodeHolder& code) : cc(&code), ir(std::move(ir)) {
}

void* A64LoweringProvider::lower(std::shared_ptr<ir::IRGraph> ir, ::asmjit::JitRuntime& runtime) {
Expand Down
Loading

0 comments on commit 0f81c3a

Please sign in to comment.