2016-03-01 15:47:10 +00:00
|
|
|
#ifndef VMUTIL_H
|
|
|
|
#define VMUTIL_H
|
|
|
|
|
2016-11-17 12:10:19 +00:00
|
|
|
#include "dobject.h"
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-11-17 15:44:41 +00:00
|
|
|
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);
|
|
|
|
|
2016-11-21 09:50:09 +00:00
|
|
|
uint16_t RegNum;
|
|
|
|
uint8_t RegType, RegCount;
|
|
|
|
// We are at 8 bytes for this struct, no matter what, so it's rather pointless to squeeze these flags into bitfields.
|
|
|
|
bool Konst, Fixed, Final, Target;
|
2016-11-17 15:44:41 +00:00
|
|
|
};
|
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
class VMFunctionBuilder
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// Keeps track of which registers are available by way of a bitmask table.
|
|
|
|
class RegAvailability
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
RegAvailability();
|
|
|
|
int GetMostUsed() { return MostUsed; }
|
|
|
|
int Get(int count); // Returns the first register in the range
|
|
|
|
void Return(int reg, int count);
|
|
|
|
bool Reuse(int regnum);
|
|
|
|
|
|
|
|
private:
|
|
|
|
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
|
|
|
|
int MostUsed;
|
|
|
|
|
|
|
|
friend class VMFunctionBuilder;
|
|
|
|
};
|
|
|
|
|
2016-10-31 16:02:47 +00:00
|
|
|
VMFunctionBuilder(int numimplicits);
|
2016-03-01 15:47:10 +00:00
|
|
|
~VMFunctionBuilder();
|
|
|
|
|
2016-10-12 22:53:59 +00:00
|
|
|
void MakeFunction(VMScriptFunction *func);
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// Returns the constant register holding the value.
|
2016-11-20 17:00:37 +00:00
|
|
|
unsigned GetConstantInt(int val);
|
|
|
|
unsigned GetConstantFloat(double val);
|
|
|
|
unsigned GetConstantAddress(void *ptr, VM_ATAG tag);
|
|
|
|
unsigned GetConstantString(FString str);
|
|
|
|
|
|
|
|
unsigned AllocConstantsInt(unsigned int count, int *values);
|
|
|
|
unsigned AllocConstantsFloat(unsigned int count, double *values);
|
|
|
|
unsigned AllocConstantsAddress(unsigned int count, void **ptrs, VM_ATAG tag);
|
|
|
|
unsigned AllocConstantsString(unsigned int count, FString *ptrs);
|
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-07-25 04:38:02 +00:00
|
|
|
// Returns the address of the next instruction to be emitted.
|
|
|
|
size_t GetAddress();
|
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
// Returns the address of the newly-emitted instruction.
|
|
|
|
size_t Emit(int opcode, int opa, int opb, int opc);
|
|
|
|
size_t Emit(int opcode, int opa, VM_SHALF opbc);
|
|
|
|
size_t Emit(int opcode, int opabc);
|
|
|
|
size_t EmitParamInt(int value);
|
|
|
|
size_t EmitLoadInt(int regnum, int value);
|
|
|
|
size_t EmitRetInt(int retnum, bool final, int value);
|
|
|
|
|
|
|
|
void Backpatch(size_t addr, size_t target);
|
|
|
|
void BackpatchToHere(size_t addr);
|
|
|
|
|
|
|
|
// Write out complete constant tables.
|
|
|
|
void FillIntConstants(int *konst);
|
|
|
|
void FillFloatConstants(double *konst);
|
|
|
|
void FillAddressConstants(FVoidObj *konst, VM_ATAG *tags);
|
|
|
|
void FillStringConstants(FString *strings);
|
|
|
|
|
|
|
|
// PARAM increases ActiveParam; CALL decreases it.
|
|
|
|
void ParamChange(int delta);
|
|
|
|
|
|
|
|
// Track available registers.
|
|
|
|
RegAvailability Registers[4];
|
|
|
|
|
2016-10-31 16:02:47 +00:00
|
|
|
// amount of implicit parameters so that proper code can be emitted for method calls
|
|
|
|
int NumImplicits;
|
2016-10-02 02:47:15 +00:00
|
|
|
|
2016-11-17 15:44:41 +00:00
|
|
|
// 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;
|
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
private:
|
|
|
|
struct AddrKonst
|
|
|
|
{
|
2016-11-20 17:00:37 +00:00
|
|
|
unsigned KonstNum;
|
2016-03-01 15:47:10 +00:00
|
|
|
VM_ATAG Tag;
|
|
|
|
};
|
2016-11-20 17:00:37 +00:00
|
|
|
|
|
|
|
TArray<int> IntConstantList;
|
|
|
|
TArray<double> FloatConstantList;
|
|
|
|
TArray<void *> AddressConstantList;
|
|
|
|
TArray<VM_ATAG> AtagConstantList;
|
|
|
|
TArray<FString> StringConstantList;
|
2016-03-01 15:47:10 +00:00
|
|
|
// These map from the constant value to its position in the constant table.
|
2016-11-20 17:00:37 +00:00
|
|
|
TMap<int, unsigned> IntConstantMap;
|
|
|
|
TMap<double, unsigned> FloatConstantMap;
|
|
|
|
TMap<void *, AddrKonst> AddressConstantMap;
|
|
|
|
TMap<FString, unsigned> StringConstantMap;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
int MaxParam;
|
|
|
|
int ActiveParam;
|
|
|
|
|
|
|
|
TArray<VMOP> Code;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2016-10-12 22:53:59 +00:00
|
|
|
void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen);
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
class FxExpression;
|
|
|
|
|
|
|
|
class FFunctionBuildList
|
|
|
|
{
|
|
|
|
struct Item
|
|
|
|
{
|
2016-10-15 12:36:08 +00:00
|
|
|
PFunction *Func = nullptr;
|
2016-10-12 22:53:59 +00:00
|
|
|
FxExpression *Code = nullptr;
|
|
|
|
PPrototype *Proto = nullptr;
|
|
|
|
VMScriptFunction *Function = nullptr;
|
2016-10-20 14:55:12 +00:00
|
|
|
FString PrintableName;
|
2016-11-06 12:14:46 +00:00
|
|
|
int StateIndex;
|
|
|
|
int StateCount;
|
2016-11-08 10:12:56 +00:00
|
|
|
int Lump;
|
2016-10-15 19:35:31 +00:00
|
|
|
bool FromDecorate;
|
2016-10-12 22:53:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
TArray<Item> mItems;
|
|
|
|
|
|
|
|
public:
|
2016-11-08 10:12:56 +00:00
|
|
|
VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate = -1, int statecnt = 0, int lumpnum = -1);
|
2016-10-12 22:53:59 +00:00
|
|
|
void Build();
|
|
|
|
};
|
|
|
|
|
|
|
|
extern FFunctionBuildList FunctionBuildList;
|
2016-03-01 15:47:10 +00:00
|
|
|
#endif
|