mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-24 04:51:41 +00:00
- use the OP_PARAM and OP_RESULT opcodes to build the function signature
This commit is contained in:
parent
5e4e9e2c2b
commit
3202c86ea7
2 changed files with 92 additions and 51 deletions
|
@ -324,7 +324,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
asmjit::CBNode *cursorBefore = cc.getCursor();
|
asmjit::CBNode *cursorBefore = cc.getCursor();
|
||||||
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
|
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature());
|
||||||
call->setInlineComment(target->PrintableName.GetChars());
|
call->setInlineComment(target->PrintableName.GetChars());
|
||||||
asmjit::CBNode *cursorAfter = cc.getCursor();
|
asmjit::CBNode *cursorAfter = cc.getCursor();
|
||||||
cc.setCursor(cursorBefore);
|
cc.setCursor(cursorBefore);
|
||||||
|
@ -460,81 +460,122 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
|
||||||
ParamOpcodes.Clear();
|
ParamOpcodes.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
asmjit::FuncSignature JitCompiler::CreateFuncSignature(VMFunction *func)
|
asmjit::FuncSignature JitCompiler::CreateFuncSignature()
|
||||||
{
|
{
|
||||||
using namespace asmjit;
|
using namespace asmjit;
|
||||||
|
|
||||||
TArray<uint8_t> args;
|
TArray<uint8_t> args;
|
||||||
FString key;
|
FString key;
|
||||||
for (unsigned int i = 0; i < func->Proto->ArgumentTypes.Size(); i++)
|
|
||||||
|
// First add parameters as args to the signature
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ParamOpcodes.Size(); i++)
|
||||||
{
|
{
|
||||||
const PType *type = func->Proto->ArgumentTypes[i];
|
if (ParamOpcodes[i]->op == OP_PARAMI)
|
||||||
if (func->ArgFlags.Size() && func->ArgFlags[i] & (VARF_Out | VARF_Ref))
|
|
||||||
{
|
|
||||||
args.Push(TypeIdOf<void*>::kTypeId);
|
|
||||||
key += "v";
|
|
||||||
}
|
|
||||||
else if (type == TypeVector2)
|
|
||||||
{
|
|
||||||
args.Push(TypeIdOf<double>::kTypeId);
|
|
||||||
args.Push(TypeIdOf<double>::kTypeId);
|
|
||||||
key += "ff";
|
|
||||||
}
|
|
||||||
else if (type == TypeVector3)
|
|
||||||
{
|
|
||||||
args.Push(TypeIdOf<double>::kTypeId);
|
|
||||||
args.Push(TypeIdOf<double>::kTypeId);
|
|
||||||
args.Push(TypeIdOf<double>::kTypeId);
|
|
||||||
key += "fff";
|
|
||||||
}
|
|
||||||
else if (type == TypeFloat64)
|
|
||||||
{
|
|
||||||
args.Push(TypeIdOf<double>::kTypeId);
|
|
||||||
key += "f";
|
|
||||||
}
|
|
||||||
else if (type == TypeString)
|
|
||||||
{
|
|
||||||
args.Push(TypeIdOf<void*>::kTypeId);
|
|
||||||
key += "s";
|
|
||||||
}
|
|
||||||
else if (type->isIntCompatible())
|
|
||||||
{
|
{
|
||||||
args.Push(TypeIdOf<int>::kTypeId);
|
args.Push(TypeIdOf<int>::kTypeId);
|
||||||
key += "i";
|
key += "i";
|
||||||
}
|
}
|
||||||
else
|
else // OP_PARAM
|
||||||
{
|
{
|
||||||
args.Push(TypeIdOf<void*>::kTypeId);
|
int bc = ParamOpcodes[i]->i16u;
|
||||||
key += "v";
|
switch (ParamOpcodes[i]->a)
|
||||||
|
{
|
||||||
|
case REGT_NIL:
|
||||||
|
case REGT_POINTER:
|
||||||
|
case REGT_POINTER | REGT_KONST:
|
||||||
|
case REGT_STRING | REGT_ADDROF:
|
||||||
|
case REGT_INT | REGT_ADDROF:
|
||||||
|
case REGT_POINTER | REGT_ADDROF:
|
||||||
|
case REGT_FLOAT | REGT_ADDROF:
|
||||||
|
args.Push(TypeIdOf<void*>::kTypeId);
|
||||||
|
key += "v";
|
||||||
|
break;
|
||||||
|
case REGT_INT:
|
||||||
|
case REGT_INT | REGT_KONST:
|
||||||
|
args.Push(TypeIdOf<int>::kTypeId);
|
||||||
|
key += "i";
|
||||||
|
break;
|
||||||
|
case REGT_STRING:
|
||||||
|
case REGT_STRING | REGT_KONST:
|
||||||
|
args.Push(TypeIdOf<void*>::kTypeId);
|
||||||
|
key += "s";
|
||||||
|
break;
|
||||||
|
case REGT_FLOAT:
|
||||||
|
case REGT_FLOAT | REGT_KONST:
|
||||||
|
args.Push(TypeIdOf<double>::kTypeId);
|
||||||
|
key += "f";
|
||||||
|
break;
|
||||||
|
case REGT_FLOAT | REGT_MULTIREG2:
|
||||||
|
args.Push(TypeIdOf<double>::kTypeId);
|
||||||
|
args.Push(TypeIdOf<double>::kTypeId);
|
||||||
|
key += "ff";
|
||||||
|
break;
|
||||||
|
case REGT_FLOAT | REGT_MULTIREG3:
|
||||||
|
args.Push(TypeIdOf<double>::kTypeId);
|
||||||
|
args.Push(TypeIdOf<double>::kTypeId);
|
||||||
|
args.Push(TypeIdOf<double>::kTypeId);
|
||||||
|
key += "fff";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
I_FatalError("Unknown REGT value passed to EmitPARAM\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VMOP *retval = pc + 1;
|
||||||
|
int numret = C;
|
||||||
|
|
||||||
uint32_t rettype = TypeIdOf<void>::kTypeId;
|
uint32_t rettype = TypeIdOf<void>::kTypeId;
|
||||||
if (func->Proto->ReturnTypes.Size() > 0)
|
|
||||||
|
// Check if first return value can be placed in the function's real return value slot
|
||||||
|
int startret = 1;
|
||||||
|
if (numret > 0)
|
||||||
{
|
{
|
||||||
const PType *type = func->Proto->ReturnTypes[0];
|
if (retval[0].op != OP_RESULT)
|
||||||
if (type == TypeFloat64)
|
|
||||||
{
|
{
|
||||||
rettype = TypeIdOf<double>::kTypeId;
|
I_FatalError("Expected OP_RESULT to follow OP_CALL\n");
|
||||||
key += "rf";
|
|
||||||
}
|
}
|
||||||
else if (type == TypeString)
|
|
||||||
{
|
int type = retval[0].b;
|
||||||
rettype = TypeIdOf<void*>::kTypeId;
|
switch (type)
|
||||||
key += "rs";
|
|
||||||
}
|
|
||||||
else if (type->isIntCompatible())
|
|
||||||
{
|
{
|
||||||
|
case REGT_INT:
|
||||||
rettype = TypeIdOf<int>::kTypeId;
|
rettype = TypeIdOf<int>::kTypeId;
|
||||||
key += "ri";
|
key += "ri";
|
||||||
}
|
break;
|
||||||
else
|
case REGT_FLOAT:
|
||||||
{
|
rettype = TypeIdOf<double>::kTypeId;
|
||||||
|
key += "rf";
|
||||||
|
break;
|
||||||
|
case REGT_STRING:
|
||||||
|
rettype = TypeIdOf<void*>::kTypeId;
|
||||||
|
key += "rs";
|
||||||
|
break;
|
||||||
|
case REGT_POINTER:
|
||||||
rettype = TypeIdOf<void*>::kTypeId;
|
rettype = TypeIdOf<void*>::kTypeId;
|
||||||
key += "rv";
|
key += "rv";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
startret = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add any additional return values as function arguments
|
||||||
|
for (int i = startret; i < numret; ++i)
|
||||||
|
{
|
||||||
|
if (retval[i].op != OP_RESULT)
|
||||||
|
{
|
||||||
|
I_FatalError("Expected OP_RESULT to follow OP_CALL\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Push(TypeIdOf<void*>::kTypeId);
|
||||||
|
key += "v";
|
||||||
|
}
|
||||||
|
|
||||||
// FuncSignature only keeps a pointer to its args array. Store a copy of each args array variant.
|
// FuncSignature only keeps a pointer to its args array. Store a copy of each args array variant.
|
||||||
static std::map<FString, std::unique_ptr<TArray<uint8_t>>> argsCache;
|
static std::map<FString, std::unique_ptr<TArray<uint8_t>>> argsCache;
|
||||||
std::unique_ptr<TArray<uint8_t>> &cachedArgs = argsCache[key];
|
std::unique_ptr<TArray<uint8_t>> &cachedArgs = argsCache[key];
|
||||||
|
|
|
@ -38,7 +38,7 @@ private:
|
||||||
#include "vmops.h"
|
#include "vmops.h"
|
||||||
#undef xx
|
#undef xx
|
||||||
|
|
||||||
static asmjit::FuncSignature CreateFuncSignature(VMFunction *sfunc);
|
asmjit::FuncSignature CreateFuncSignature();
|
||||||
|
|
||||||
void Setup();
|
void Setup();
|
||||||
void CreateRegisters();
|
void CreateRegisters();
|
||||||
|
|
Loading…
Reference in a new issue