Merge branch 'asmjit' into weapon_scriptification

# Conflicts:
#	src/gi.cpp
#	wadsrc/static/zscript/base.txt
This commit is contained in:
Christoph Oelckers 2018-11-26 00:14:44 +01:00
commit 47b1fa774d
51 changed files with 1809 additions and 1239 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,23 +10747,29 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
//
//==========================================================================
int BuiltinNameToClass(VM_ARGS)
static PClass *NativeNameToClass(int _clsname, PClass *desttype)
{
PARAM_PROLOGUE;
PARAM_NAME(clsname);
PARAM_CLASS(desttype, DObject);
PClass *cls = nullptr;
FName clsname = ENamedName(_clsname);
if (clsname != NAME_None)
{
cls = PClass::FindClass(clsname);
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 +10781,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 +10873,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 +10891,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

@ -944,6 +944,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

@ -9,6 +9,7 @@ extern PStruct *TypeVector3;
static void OutputJitLog(const asmjit::StringLogger &logger);
static TArray<uint8_t*> JitBlocks;
static TArray<uint8_t*> JitFrames;
static size_t JitBlockPos = 0;
static size_t JitBlockSize = 0;
@ -61,6 +62,25 @@ static void *AllocJitMemory(size_t size)
#define UWOP_SAVE_XMM128_FAR 9
#define UWOP_PUSH_MACHFRAME 10
void JitRelease()
{
#ifdef _WIN64
for (auto p : JitFrames)
{
RtlDeleteFunctionTable((PRUNTIME_FUNCTION)p);
}
#endif
for (auto p : JitBlocks)
{
asmjit::OSUtils::releaseVirtualMemory(p, 1024 * 1024);
}
JitFrames.Clear();
JitBlocks.Clear();
JitBlockPos = 0;
JitBlockSize = 0;
}
static TArray<uint16_t> CreateUnwindInfo(asmjit::CCFunc *func)
{
using namespace asmjit;
@ -276,6 +296,7 @@ static void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func)
table[0].EndAddress = (DWORD)(ptrdiff_t)(endaddr - baseaddr);
table[0].UnwindInfoAddress = (DWORD)(ptrdiff_t)(unwindptr - baseaddr);
BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr);
JitFrames.Push((uint8_t*)table);
if (result == 0)
I_FatalError("RtlAddFunctionTable failed");
#endif

View file

@ -317,13 +317,16 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
{
using namespace asmjit;
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
if ((pc - 1)->op == OP_VTBL)
{
I_FatalError("Native direct member function calls not implemented\n");
}
asmjit::CBNode *cursorBefore = cc.getCursor();
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
asmjit::CBNode *cursorAfter = cc.getCursor();
cc.setCursor(cursorBefore);
X86Gp tmp;
X86Xmm tmp2;
@ -398,6 +401,8 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
}
}
cc.setCursor(cursorAfter);
if (numparams != B)
I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions\n");
@ -461,7 +466,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

@ -53,6 +53,8 @@ extern FMemArena ClassDataAllocator;
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return
#define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function
void JitRelease();
typedef unsigned char VM_UBYTE;
typedef signed char VM_SBYTE;
@ -432,6 +434,8 @@ public:
f->~VMFunction();
}
AllFunctions.Clear();
// also release any JIT data
JitRelease();
}
static void CreateRegUseInfo()
{
@ -511,6 +515,7 @@ bool AssertObject(void * ob);
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, self->GetClass());
#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass());
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type *x = (type *)param[p].a;
#define PARAM_OUTPOINTER_AT(p,x,type) assert((p) < numparam); type *x = (type *)param[p].a;
#define PARAM_POINTERTYPE_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type x = (type )param[p].a;
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER && AssertObject(param[p].a)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
@ -534,6 +539,7 @@ bool AssertObject(void * ob);
#define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
#define PARAM_STATE_ACTION(x) ++paramnum; PARAM_STATE_ACTION_AT(paramnum,x)
#define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
#define PARAM_OUTPOINTER(x,type) ++paramnum; PARAM_OUTPOINTER_AT(paramnum,x,type)
#define PARAM_POINTERTYPE(x,type) ++paramnum; PARAM_POINTERTYPE_AT(paramnum,x,type)
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
@ -559,6 +565,7 @@ struct AFuncDesc
const char *FuncName;
actionf_p Function;
VMNativeFunction **VMPointer;
void *DirectNative;
};
#if defined(_MSC_VER)
@ -579,10 +586,19 @@ 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_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, reinterpret_cast<void*>(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)
#define DEFINE_ACTION_FUNCTION(cls, name) \
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, nullptr }; \
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)

View file

@ -80,6 +80,7 @@ void VMFunction::CreateRegUse()
return;
}
assert(Proto->isPrototype());
for (auto arg : Proto->ArgumentTypes)
{
count += arg? arg->GetRegCount() : 1;
@ -87,14 +88,20 @@ void VMFunction::CreateRegUse()
uint8_t *regp;
RegTypes = regp = (uint8_t*)ClassDataAllocator.Alloc(count);
count = 0;
for (auto arg : Proto->ArgumentTypes)
for (unsigned i = 0; i < Proto->ArgumentTypes.Size(); i++)
{
auto arg = Proto->ArgumentTypes[i];
auto flg = ArgFlags.Size() > i ? ArgFlags[i] : 0;
if (arg == nullptr)
{
// Marker for start of varargs.
*regp++ = REGT_NIL;
}
else for (int i = 0; i < arg->GetRegCount(); i++)
else if ((flg & VARF_Out) && !arg->isPointer())
{
*regp++ = REGT_POINTER;
}
else for (int j = 0; j < arg->GetRegCount(); j++)
{
*regp++ = arg->GetRegType();
}

1267
src/scripting/vmthunks.cpp Normal file

File diff suppressed because it is too large Load diff