- 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:
Christoph Oelckers 2018-11-25 11:41:29 +01:00
parent b267252a09
commit a501a22b28
7 changed files with 98 additions and 92 deletions

View file

@ -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);

View file

@ -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)
//==========================================================================

View file

@ -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

View file

@ -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();

View file

@ -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";

View file

@ -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 }; \

View file

@ -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);