Juliean said:
Hold on, now. Thats already what I'm doing (=writing my own OpCodes)
Ah ok, maybe I misunderstood the term “asm-blocks” you used in the first few posts ?
Juliean said:
that its still slower than native code
It will always be slower than native code written in C++ at least. Look at how long Microsoft worked on C# and it still is considered bad for huge computational tasks like verifying a Bitcoin transmission (which is horrybly slow, I tried that).
Ok so I might not got what exactly is your issue in calling functions from your OpCode. My route to achieve that would have been to have a call instruction or maybe two, one for calling a script and one for switching into C++ and finally some meta instructions that know about the signature of the function or you use a generic wrapper method or a wrapper struct that is not more complicated to the user than a simple function pointer, like I did for my embedded console.
Especially if you limit the calling convention to only cdecl for now, this would be a lot easier by an implicit ctor added to the wrapper struct.
template<typename ret do_if(ORDER, _separator) variadic_decl(typename Args, ORDER)> struct StaticCallContext<ret (variadic_decl(Args, ORDER))>
{
public:
typedef ret (*FunctionPointer) (variadic_decl(Args, ORDER));
...
template<FunctionPointer type> static force_inline void AnonymousFunctor(void* target, void** args)
{
*reinterpret_cast<typename SE::TypeTraits::Const::Remove<typename SE::TypeTraits::Reference::Remove<ret>::Result>::Result*>(args[ORDER]) = type(variadic_deduce(Args, args, ORDER));
(void)target;
(void)args;
}
};
My code looks a bit template/macro heavy because I aim to set on the '99 standard and baerly C++11 features. My deduce macro looks like this
...
#define XP_VARIADIC_DEDUCE_ARGSVAL19(type_name, args_name) XP_VARIADIC_DEDUCE_ARGSVAL18(type_name, args_name), *reinterpret_cast<typename SE::TypeTraits::Reference::Remove<JOIN(type_name, 18)>::Result*>(args_name[18])
#define XP_VARIADIC_DEDUCE_ARGSVAL20(type_name, args_name) XP_VARIADIC_DEDUCE_ARGSVAL19(type_name, args_name), *reinterpret_cast<typename SE::TypeTraits::Reference::Remove<JOIN(type_name, 19)>::Result*>(args_name[19])
#define XP_VARIADIC_DEDUCE_ARGSVAL21(type_name, args_name) XP_VARIADIC_DEDUCE_ARGSVAL20(type_name, args_name), *reinterpret_cast<typename SE::TypeTraits::Reference::Remove<JOIN(type_name, 20)>::Result*>(args_name[20])
#define variadic_deduce(type_name, args_name, count) JOIN(XP_VARIADIC_DEDUCE_ARGSVAL, count)(type_name, args_name)
The code simply assumes an array of type void* which points to the arguments passed into the surrounding call like I do in my flex-type (which is like C# dynamic) or a stack or whatever location you save the parameters to. I don't perform further checks for signature or number of arguments so maybe you want to do that in your code. My macro code then simply deduces the array acording to the number and type of template arguments, which are named by the variadicdecl macro from 0 to _N (where N is the amount of arguments), thats why the deduce macro is able to access them for each position and finally performs a reinterpret cast.
I support different calling conventions as same as member-function pointers so I had to split those helper methods into different templates but as I wrote above, if you intend to support just a single calling convention, an implicit ctor of a template struct might simplify everything for you and your users