- separated the code generation from the DECORATE parser and cleaned up the interface to the code generator. Most importantly, the VMScriptFunctions are now preallocated when being added to the list of functions to compile and will be filled in later by the code generator. This allowed the removal of some ugly maintenance code.

This commit is contained in:
Christoph Oelckers 2016-10-13 00:53:59 +02:00
commit a72fbb771f
16 changed files with 276 additions and 263 deletions

View file

@ -1020,4 +1020,5 @@ class PFunction;
PFunction *FindGlobalActionFunction(const char *name);
#endif

View file

@ -32,6 +32,10 @@
*/
#include "vmbuilder.h"
#include "codegeneration/thingdef_exp.h"
#include "info.h"
#include "m_argv.h"
#include "thingdef.h"
//==========================================================================
//
@ -68,10 +72,8 @@ VMFunctionBuilder::~VMFunctionBuilder()
//
//==========================================================================
VMScriptFunction *VMFunctionBuilder::MakeFunction()
void VMFunctionBuilder::MakeFunction(VMScriptFunction *func)
{
VMScriptFunction *func = new VMScriptFunction;
func->Alloc(Code.Size(), NumIntConstants, NumFloatConstants, NumStringConstants, NumAddressConstants);
// Copy code block.
@ -106,8 +108,6 @@ VMScriptFunction *VMFunctionBuilder::MakeFunction()
// entries on the parameter stack, but it means the caller probably
// did something wrong.
assert(ActiveParam == 0);
return func;
}
//==========================================================================
@ -634,3 +634,113 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc)
{
Backpatch(loc, Code.Size());
}
//==========================================================================
//
// FFunctionBuildList
//
// This list contains all functions yet to build.
// All adding functions return a VMFunction - either a complete one
// for native functions or an empty VMScriptFunction for scripted ones
// This VMScriptFunction object later gets filled in with the actual
// info, but we get the pointer right after registering the function
// with the builder.
//
//==========================================================================
FFunctionBuildList FunctionBuildList;
VMFunction *FFunctionBuildList::AddFunction(PClass *cls, FxExpression *code, const FString &name, bool statecall)
{
auto func = code->GetDirectFunction();
if (func != nullptr)
{
delete code;
return func;
}
Printf("Adding %s\n", name.GetChars());
Item it;
it.Class = cls;
it.Code = code;
it.DumpName = name;
it.Function = new VMScriptFunction;
it.Proto = nullptr;
it.type = statecall;
mItems.Push(it);
return it.Function;
}
void FFunctionBuildList::Build()
{
int errorcount = 0;
int codesize = 0;
FILE *dump = nullptr;
if (Args->CheckParm("-dumpdisasm")) dump = fopen("disasm.txt", "w");
for (auto &item : mItems)
{
assert(item.Code != NULL);
// We don't know the return type in advance for anonymous functions.
FCompileContext ctx(item.Class, nullptr);
item.Code = item.Code->Resolve(ctx);
item.Proto = ctx.ReturnProto;
// Make sure resolving it didn't obliterate it.
if (item.Code != nullptr)
{
VMFunctionBuilder buildit(true);
assert(item.Proto != nullptr);
int numargs;
int flags;
// Kludge alert. This needs to be done in a more universal fashion.
// Right now there's only action and damage functions, so for the time being
// this will do to get the whole thing started first.
if (item.type == 1) // anonymous action function
{
numargs = NAP;
flags = VARF_Method | VARF_Action;
}
else
{
numargs = 1;
flags = VARF_Method;
}
// Generate prototype for this anonymous function
buildit.Registers[REGT_POINTER].Get(numargs);
TArray<PType *> args(numargs);
SetImplicitArgs(&args, nullptr, item.Class, flags);
VMScriptFunction *sfunc = item.Function;
item.Function->Proto = NewPrototype(item.Proto->ReturnTypes, args);
// Emit code
item.Code->Emit(&buildit);
buildit.MakeFunction(item.Function);
item.Function->NumArgs = numargs;
if (dump != nullptr)
{
char label[64];
int labellen = mysnprintf(label, countof(label), item.DumpName,
item.Class->TypeName.GetChars());
DumpFunction(dump, sfunc, label, labellen);
codesize += sfunc->CodeSize;
}
}
delete item.Code;
}
if (dump != nullptr)
{
fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4);
fclose(dump);
}
}

View file

@ -26,7 +26,7 @@ public:
VMFunctionBuilder(bool checkself = false);
~VMFunctionBuilder();
VMScriptFunction *MakeFunction();
void MakeFunction(VMScriptFunction *func);
// Returns the constant register holding the value.
int GetConstantInt(int val);
@ -87,4 +87,34 @@ private:
};
void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen);
//==========================================================================
//
//
//
//==========================================================================
class FxExpression;
class FFunctionBuildList
{
struct Item
{
PClass *Class = nullptr;
FxExpression *Code = nullptr;
PPrototype *Proto = nullptr;
VMScriptFunction *Function = nullptr;
FString DumpName;
int type; // temporary kludge
};
TArray<Item> mItems;
public:
VMFunction *AddFunction(PClass *cls, FxExpression *code, const FString &name, bool statecall = false);
void Build();
};
extern FFunctionBuildList FunctionBuildList;
#endif

View file

@ -33,6 +33,7 @@
#include "vm.h"
#include "c_console.h"
#include "templates.h"
#define NOP MODE_AUNUSED | MODE_BUNUSED | MODE_CUNUSED
@ -598,3 +599,21 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const
}
return col;
}
//==========================================================================
//
// Do some postprocessing after everything has been defined
//
//==========================================================================
void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen)
{
const char *marks = "=======================================================";
fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n",
sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam);
VMDumpConstants(dump, sfunc);
fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code);
VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc);
}