mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- define the built-in functions defined in codegen.cpp through the regular interface instead uf just hacking them into the symbol table with incompletely set up data.
- added direct native variants to these builtins and fixed problems with builtin processing.
This commit is contained in:
parent
b267252a09
commit
a501a22b28
7 changed files with 98 additions and 92 deletions
|
@ -259,20 +259,9 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func, const uint8_t *reginfo)
|
||||
static PFunction *FindBuiltinFunction(FName funcname)
|
||||
{
|
||||
PSymbol *sym = Namespaces.GlobalNamespace->Symbols.FindSymbol(funcname, false);
|
||||
if (sym == nullptr)
|
||||
{
|
||||
PSymbolVMFunction *symfunc = Create<PSymbolVMFunction>(funcname);
|
||||
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
|
||||
calldec->PrintableName = funcname.GetChars();
|
||||
calldec->RegTypes = reginfo;
|
||||
symfunc->Function = calldec;
|
||||
sym = symfunc;
|
||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(sym);
|
||||
}
|
||||
return sym;
|
||||
return dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->FindSymbol(funcname, true));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -5471,33 +5460,35 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinRandom(VM_ARGS)
|
||||
static int NativeRandom(FRandom *rng, int min, int max)
|
||||
{
|
||||
if (max < min)
|
||||
{
|
||||
std::swap(max, min);
|
||||
}
|
||||
return (*rng)(max - min + 1) + min;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandom, NativeRandom)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(rng, FRandom);
|
||||
PARAM_INT(min);
|
||||
PARAM_INT(max);
|
||||
if (max < min)
|
||||
{
|
||||
std::swap(max, min);
|
||||
}
|
||||
ACTION_RETURN_INT((*rng)(max - min + 1) + min);
|
||||
ACTION_RETURN_INT(NativeRandom(rng, min, max));
|
||||
}
|
||||
|
||||
ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
// Call DecoRandom to generate a random number.
|
||||
VMFunction *callfunc;
|
||||
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
assert(sym);
|
||||
callfunc = sym->Variants[0].Implementation;
|
||||
assert(min && max);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameter(build, min);
|
||||
emitters.AddParameter(build, max);
|
||||
|
@ -5596,12 +5587,10 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
|
||||
// Call BuiltinRandom to generate a random number.
|
||||
VMFunction *callfunc;
|
||||
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
assert(sym);
|
||||
callfunc = sym->Variants[0].Implementation;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
|
@ -5694,13 +5683,8 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinFRandom(VM_ARGS)
|
||||
static double NativeFRandom(FRandom *rng, double min, double max)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(rng, FRandom);
|
||||
PARAM_FLOAT(min);
|
||||
PARAM_FLOAT(max);
|
||||
|
||||
int random = (*rng)(0x40000000);
|
||||
double frandom = random / double(0x40000000);
|
||||
|
||||
|
@ -5708,20 +5692,29 @@ int BuiltinFRandom(VM_ARGS)
|
|||
{
|
||||
std::swap(max, min);
|
||||
}
|
||||
ACTION_RETURN_FLOAT(frandom * (max - min) + min);
|
||||
return frandom * (max - min) + min;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinFRandom, NativeFRandom)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(rng, FRandom);
|
||||
PARAM_FLOAT(min);
|
||||
PARAM_FLOAT(max);
|
||||
|
||||
ACTION_RETURN_FLOAT(NativeFRandom(rng, min, max));
|
||||
}
|
||||
|
||||
ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
// Call the BuiltinFRandom function to generate a floating point random number..
|
||||
VMFunction *callfunc;
|
||||
static uint8_t reginfo[] = { REGT_POINTER, REGT_FLOAT, REGT_FLOAT };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinFRandom);
|
||||
|
||||
assert(sym);
|
||||
callfunc = sym->Variants[0].Implementation;
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
assert(min && max);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
|
@ -5776,7 +5769,12 @@ FxExpression *FxRandom2::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinRandom2(VM_ARGS)
|
||||
static int NativeRandom2(FRandom *rng, int maskval)
|
||||
{
|
||||
return rng->Random2(maskval);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandom2, NativeRandom2)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(rng, FRandom);
|
||||
|
@ -5794,12 +5792,10 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
// Call the BuiltinRandom function to generate the random number.
|
||||
VMFunction *callfunc;
|
||||
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom2, BuiltinRandom2, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinRandom2);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
assert(sym);
|
||||
callfunc = sym->Variants[0].Implementation;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
|
||||
|
@ -5853,7 +5849,12 @@ FxExpression *FxRandomSeed::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinRandomSeed(VM_ARGS)
|
||||
static void NativeRandomSeed(FRandom *rng, int seed)
|
||||
{
|
||||
rng->Init(seed);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandomSeed, NativeRandomSeed)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(rng, FRandom)
|
||||
|
@ -5866,12 +5867,10 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
// Call DecoRandom to generate a random number.
|
||||
VMFunction *callfunc;
|
||||
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandomSeed, BuiltinRandomSeed, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinRandomSeed);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
assert(sym);
|
||||
callfunc = sym->Variants[0].Implementation;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
|
@ -8525,7 +8524,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinCallLineSpecial(VM_ARGS)
|
||||
DEFINE_ACTION_FUNCTION(DObject, BuiltinCallLineSpecial)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(special);
|
||||
|
@ -8545,11 +8544,10 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
|
||||
// Call the BuiltinCallLineSpecial function to perform the desired special.
|
||||
static uint8_t reginfo[] = { REGT_INT, REGT_POINTER, REGT_INT, REGT_INT, REGT_INT, REGT_INT, REGT_INT };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
VMFunction *callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
assert(sym);
|
||||
auto callfunc = sym->Variants[0].Implementation;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
|
||||
|
@ -10749,12 +10747,8 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinNameToClass(VM_ARGS)
|
||||
static PClass *NativeNameToClass(FName clsname, PClass *desttype)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(clsname);
|
||||
PARAM_CLASS(desttype, DObject);
|
||||
|
||||
PClass *cls = nullptr;
|
||||
if (clsname != NAME_None)
|
||||
{
|
||||
|
@ -10762,10 +10756,19 @@ int BuiltinNameToClass(VM_ARGS)
|
|||
if (cls != nullptr && (cls->VMType == nullptr || !cls->IsDescendantOf(desttype)))
|
||||
{
|
||||
// does not match required parameters or is invalid.
|
||||
cls = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_POINTER(cls);
|
||||
return cls;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinNameToClass, NativeNameToClass)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(clsname);
|
||||
PARAM_CLASS(desttype, DObject);
|
||||
|
||||
ACTION_RETURN_POINTER(NativeNameToClass(clsname, desttype));
|
||||
}
|
||||
|
||||
ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
||||
|
@ -10777,12 +10780,10 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
|
||||
// Call the BuiltinNameToClass function to convert from 'name' to class.
|
||||
VMFunction *callfunc;
|
||||
static uint8_t reginfo[] = { REGT_INT, REGT_POINTER };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinNameToClass);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
assert(sym);
|
||||
callfunc = sym->Variants[0].Implementation;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
emitters.AddParameter(build, basex);
|
||||
|
@ -10871,12 +10872,17 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinClassCast(VM_ARGS)
|
||||
static PClass *NativeClassCast(PClass *from, PClass *to)
|
||||
{
|
||||
return from && to && from->IsDescendantOf(to) ? from : nullptr;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinClassCast, NativeClassCast)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS(from, DObject);
|
||||
PARAM_CLASS(to, DObject);
|
||||
ACTION_RETURN_POINTER(from && to && from->IsDescendantOf(to) ? from : nullptr);
|
||||
ACTION_RETURN_POINTER(NativeClassCast(from, to));
|
||||
}
|
||||
|
||||
ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
|
||||
|
@ -10884,12 +10890,10 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit clsname = basex->Emit(build);
|
||||
|
||||
VMFunction *callfunc;
|
||||
static uint8_t reginfo[] = { REGT_POINTER, REGT_POINTER };
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast, reginfo);
|
||||
auto sym = FindBuiltinFunction(NAME_BuiltinClassCast);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
assert(sym);
|
||||
callfunc = sym->Variants[0].Implementation;
|
||||
|
||||
FunctionCallEmitter emitters(callfunc);
|
||||
emitters.AddParameter(clsname, false);
|
||||
|
|
|
@ -52,7 +52,6 @@ IMPLEMENT_CLASS(PSymbolConstNumeric, false, false);
|
|||
IMPLEMENT_CLASS(PSymbolConstString, false, false);
|
||||
IMPLEMENT_CLASS(PSymbolTreeNode, false, false)
|
||||
IMPLEMENT_CLASS(PSymbolType, false, false)
|
||||
IMPLEMENT_CLASS(PSymbolVMFunction, false, false)
|
||||
IMPLEMENT_CLASS(PFunction, false, false)
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -37,16 +37,6 @@ protected:
|
|||
|
||||
// A VM function ------------------------------------------------------------
|
||||
|
||||
class PSymbolVMFunction : public PSymbol
|
||||
{
|
||||
DECLARE_CLASS(PSymbolVMFunction, PSymbol);
|
||||
public:
|
||||
VMFunction *Function;
|
||||
|
||||
PSymbolVMFunction(FName name) : PSymbol(name) {}
|
||||
PSymbolVMFunction() : PSymbol(NAME_None) {}
|
||||
};
|
||||
|
||||
// A symbol for a type ------------------------------------------------------
|
||||
|
||||
class PSymbolType : public PSymbol
|
||||
|
|
|
@ -933,6 +933,7 @@ void InitThingdef()
|
|||
assert(afunc->VMPointer != NULL);
|
||||
*(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->FuncName);
|
||||
(*(afunc->VMPointer))->PrintableName.Format("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName);
|
||||
(*(afunc->VMPointer))->DirectNativeCall = afunc->DirectNative;
|
||||
AFTable.Push(*afunc);
|
||||
}
|
||||
AFTable.ShrinkToFit();
|
||||
|
|
|
@ -461,7 +461,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature(VMFunction *func)
|
|||
for (unsigned int i = 0; i < func->Proto->ArgumentTypes.Size(); i++)
|
||||
{
|
||||
const PType *type = func->Proto->ArgumentTypes[i];
|
||||
if (func->ArgFlags[i] & (VARF_Out | VARF_Ref))
|
||||
if (func->ArgFlags.Size() && func->ArgFlags[i] & (VARF_Out | VARF_Ref))
|
||||
{
|
||||
args.Push(TypeIdOf<void*>::kTypeId);
|
||||
key += "v";
|
||||
|
|
|
@ -555,6 +555,7 @@ struct AFuncDesc
|
|||
const char *FuncName;
|
||||
actionf_p Function;
|
||||
VMNativeFunction **VMPointer;
|
||||
void *DirectNative;
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
@ -575,14 +576,16 @@ struct AFuncDesc
|
|||
// Macros to handle action functions. These are here so that I don't have to
|
||||
// change every single use in case the parameters change.
|
||||
|
||||
#define DEFINE_ACTION_FUNCTION(cls, name) \
|
||||
#define DEFINE_ACTION_FUNCTION_NATIVE(cls, name, native) \
|
||||
static int AF_##cls##_##name(VM_ARGS); \
|
||||
VMNativeFunction *cls##_##name##_VMPtr; \
|
||||
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr }; \
|
||||
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr, native }; \
|
||||
extern AFuncDesc const *const cls##_##name##_HookPtr; \
|
||||
MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \
|
||||
static int AF_##cls##_##name(VM_ARGS)
|
||||
|
||||
#define DEFINE_ACTION_FUNCTION(cls, name) DEFINE_ACTION_FUNCTION_NATIVE(cls, name, nullptr)
|
||||
|
||||
// cls is the scripted class name, icls the internal one (e.g. player_t vs. Player)
|
||||
#define DEFINE_FIELD_X(cls, icls, name) \
|
||||
static const FieldDesc VMField_##icls##_##name = { "A" #cls, #name, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), 0 }; \
|
||||
|
|
|
@ -373,6 +373,15 @@ class Object native
|
|||
{
|
||||
native bool bDestroyed;
|
||||
|
||||
// These must be defined in some class, so that the compiler can find them. Object is just fine, as long as they are private to external code.
|
||||
private native int BuiltinRandom(voidptr rng, int min, int max);
|
||||
private native double BuiltinFRandom(voidptr rng, double min, double max);
|
||||
private native int BuiltinRandom2(voidptr rng, int mask);
|
||||
private native void BuiltinRandomSeed(voidptr rng, int seed);
|
||||
private native int BuiltinCallLineSpecial(int special, Actor activator, int arg1, int arg2, int arg3, int arg4, int arg5);
|
||||
private native Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
|
||||
private native Object BuiltinClassCast(Object inptr, Class<Object> test);
|
||||
|
||||
// These really should be global functions...
|
||||
native static String G_SkillName();
|
||||
native static int G_SkillPropertyInt(int p);
|
||||
|
|
Loading…
Reference in a new issue