- implemented code generation for stack variables.

- fixed code generation for using local variables as array index. This must use a different register for the array element offset because the original register may not be overwritten.
This commit is contained in:
Christoph Oelckers 2016-11-17 16:44:41 +01:00
parent d86f03e2e0
commit 2cc48ec378
9 changed files with 310 additions and 96 deletions

View file

@ -818,7 +818,6 @@ public:
void InitExtra(void *addr);
void DestroyExtra(void *addr);
void SetExtraSpecial(PType *type, unsigned offset);
int AllocExtraStack(PType *type);
};
@ -1047,6 +1046,7 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self);
#define ACTION_RETURN_VEC3(v) do { DVector3 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector(u); return 1; } return 0; } while(0)
#define ACTION_RETURN_INT(v) do { int u = v; if (numret > 0) { assert(ret != NULL); ret->SetInt(u); return 1; } return 0; } while(0)
#define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v)
#define ACTION_RETURN_STRING(v) do { FString u = v; if (numret > 0) { assert(ret != NULL); ret->SetString(u); return 1; } return 0; } while(0)
// Checks to see what called the current action function
#define ACTION_CALL_FROM_ACTOR() (stateinfo == nullptr || stateinfo->mStateType == STATE_Actor)

View file

@ -718,6 +718,13 @@ void FFunctionBuildList::Build()
FScriptPosition::StrictErrors = !item.FromDecorate;
item.Code = item.Code->Resolve(ctx);
// If we need extra space, load the frame pointer into a register so that we do not have to call the wasteful LFP instruction more than once.
if (item.Function->ExtraSpace > 0)
{
buildit.FramePointer = ExpEmit(&buildit, REGT_POINTER);
buildit.FramePointer.Fixed = true;
buildit.Emit(OP_LFP, buildit.FramePointer.RegNum);
}
// Make sure resolving it didn't obliterate it.
if (item.Code != nullptr)

View file

@ -3,6 +3,19 @@
#include "dobject.h"
class VMFunctionBuilder;
struct ExpEmit
{
ExpEmit() : RegNum(0), RegType(REGT_NIL), RegCount(1), Konst(false), Fixed(false), Final(false), Target(false) {}
ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), RegCount(1), Konst(konst), Fixed(fixed), Final(false), Target(false) {}
ExpEmit(VMFunctionBuilder *build, int type, int count = 1);
void Free(VMFunctionBuilder *build);
void Reuse(VMFunctionBuilder *build);
BYTE RegNum, RegType, RegCount, Konst:1, Fixed : 1, Final : 1, Target : 1;
};
class VMFunctionBuilder
{
public:
@ -63,6 +76,9 @@ public:
// amount of implicit parameters so that proper code can be emitted for method calls
int NumImplicits;
// keep the frame pointer, if needed, in a register because the LFP opcode is hideously inefficient, requiring more than 20 instructions on x64.
ExpEmit FramePointer;
private:
struct AddrKonst
{

View file

@ -182,15 +182,11 @@ void VMScriptFunction::DestroyExtra(void *addr)
}
}
void VMScriptFunction::SetExtraSpecial(PType *type, unsigned offset)
{
type->SetDefaultValue(nullptr, offset, &SpecialInits);
}
int VMScriptFunction::AllocExtraStack(PType *type)
{
int address = ((ExtraSpace + type->Align - 1) / type->Align) * type->Align;
ExtraSpace = address + type->Size;
type->SetDefaultValue(nullptr, address, &SpecialInits);
return address;
}