Eliminate .mreg section

- Member variables are now declared all in one place: InitThingdef(). They
  are not partially defined in thingdef_expression.cpp and further refined
  in actor.txt.
- This left ParseNativeVariable() parsing only functions, so it has been
  renamed to ParseNativeFunction().
- Note that their declarations in InitThingdef() are expected to be
  temporary.
This commit is contained in:
Randy Heit 2015-03-14 22:07:52 -05:00
parent 1e7cce5a2c
commit 8cb269388e
10 changed files with 69 additions and 241 deletions

View File

@ -53,7 +53,7 @@
// for initialized read-only data.)
#pragma comment(linker, "/merge:.areg=.rdata /merge:.creg=.rdata /merge:.greg=.rdata")
#pragma comment(linker, "/merge:.mreg=.rdata /merge:.yreg=.rdata")
#pragma comment(linker, "/merge:.yreg=.rdata")
#pragma section(".areg$a",read)
__declspec(allocate(".areg$a")) void *const ARegHead = 0;
@ -64,9 +64,6 @@ __declspec(allocate(".creg$a")) void *const CRegHead = 0;
#pragma section(".greg$a",read)
__declspec(allocate(".greg$a")) void *const GRegHead = 0;
#pragma section(".mreg$a",read)
__declspec(allocate(".mreg$a")) void *const MRegHead = 0;
#pragma section(".yreg$a",read)
__declspec(allocate(".yreg$a")) void *const YRegHead = 0;
@ -101,7 +98,6 @@ __declspec(allocate(".yreg$a")) void *const YRegHead = 0;
void *const ARegHead __attribute__((section(SECTION_AREG))) = 0;
void *const CRegHead __attribute__((section(SECTION_CREG))) = 0;
void *const GRegHead __attribute__((section(SECTION_GREG))) = 0;
void *const MRegHead __attribute__((section(SECTION_MREG))) = 0;
void *const YRegHead __attribute__((section(SECTION_YREG))) = 0;
#else

View File

@ -50,10 +50,6 @@ extern REGINFO CRegTail;
extern REGINFO GRegHead;
extern REGINFO GRegTail;
// List of variables
extern REGINFO MRegHead;
extern REGINFO MRegTail;
// List of MAPINFO map options
extern REGINFO YRegHead;
extern REGINFO YRegTail;

View File

@ -461,6 +461,7 @@ class PField : public PSymbol
public:
PField(FName name, PType *type) : PSymbol(name), Offset(0), Type(type), Flags(0) {}
PField(FName name, PType *type, DWORD flags) : PSymbol(name), Offset(0), Type(type), Flags(flags) {}
PField(FName name, PType *type, DWORD flags, unsigned offset) : PSymbol(name), Offset(offset), Type(type), Flags(flags) {}
unsigned int Offset;
PType *Type;

View File

@ -303,6 +303,16 @@ xx(Sqrt)
xx(CheckClass)
xx(IsPointerEqual)
xx(Pick)
xx(Mass)
xx(VelX)
xx(VelY)
xx(VelZ)
xx(Accuracy)
xx(Stamina)
xx(Radius)
xx(ReactionTime)
xx(MeleeRange)
xx(Speed)
// Various actor names which are used internally
xx(MapSpot)

View File

@ -280,16 +280,7 @@ struct FPropertyInfo
int category;
};
struct FVariableInfo
{
const char *name;
intptr_t address;
const PClass * const *owner;
};
FPropertyInfo *FindProperty(const char * string);
FVariableInfo *FindVariable(const char * string, const PClass *cls);
int MatchString (const char *in, const char **strings);
@ -335,15 +326,6 @@ int MatchString (const char *in, const char **strings);
int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(NULL, params[(no)+2].s);
#define DEFINE_MEMBER_VARIABLE(name, cls) \
static FVariableInfo GlobalDef__##name = { #name, static_cast<intptr_t>(myoffsetof(cls, name)), &RUNTIME_CLASS_CASTLESS(cls) }; \
MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name;
#define DEFINE_MEMBER_VARIABLE_ALIAS(name, alias, cls) \
static FVariableInfo GlobalDef__##name = { #name, static_cast<intptr_t>(myoffsetof(cls, alias)), &RUNTIME_CLASS_CASTLESS(cls) }; \
MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name;
// 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 DECLARE_ACTION(name) extern VMNativeFunction *name##_VMPtr;

View File

@ -46,7 +46,6 @@
static TArray<FPropertyInfo*> properties;
static TArray<AFuncDesc> AFTable;
static TArray<FVariableInfo*> variables;
//==========================================================================
//
@ -533,42 +532,6 @@ AFuncDesc *FindFunction(const char * string)
}
//==========================================================================
//
// Find a variable by name using a binary search
//
//==========================================================================
FVariableInfo *FindVariable(const char * string, const PClass *cls)
{
int min = 0, max = variables.Size()-1;
while (min <= max)
{
int mid = (min + max) / 2;
int lexval;
if (cls < *variables[mid]->owner) lexval = -1;
else if (cls > *variables[mid]->owner) lexval = 1;
else lexval = stricmp (string, variables[mid]->name);
if (lexval == 0)
{
return variables[mid];
}
else if (lexval > 0)
{
min = mid + 1;
}
else
{
max = mid - 1;
}
}
return NULL;
}
//==========================================================================
//
// Find an action function in AActor's table
@ -602,15 +565,6 @@ static int STACK_ARGS funccmp(const void * a, const void * b)
return stricmp( ((AFuncDesc*)a)->Name, ((AFuncDesc*)b)->Name);
}
static int STACK_ARGS varcmp(const void * a, const void * b)
{
FVariableInfo *A = *(FVariableInfo**)a;
FVariableInfo *B = *(FVariableInfo**)b;
if (A->owner < B->owner) return -1;
if (A->owner > B->owner) return 1;
return stricmp(A->name, B->name);
}
//==========================================================================
//
// Initialization
@ -654,17 +608,39 @@ void InitThingdef()
qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp);
}
// Create a sorted list of native variables
if (variables.Size() == 0)
{
FAutoSegIterator probe(MRegHead, MRegTail);
while (*++probe != NULL)
{
variables.Push((FVariableInfo *)*probe);
// Define some member variables we feel like exposing to the user
PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols;
PType *array5 = NewArray(TypeSInt32, 5);
symt.AddSymbol(new PField(NAME_Alpha, TypeFixed, VARF_Native, myoffsetof(AActor,alpha)));
symt.AddSymbol(new PField(NAME_Angle, TypeAngle, VARF_Native, myoffsetof(AActor,angle)));
symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor,args)));
symt.AddSymbol(new PField(NAME_CeilingZ, TypeFixed, VARF_Native, myoffsetof(AActor,ceilingz)));
symt.AddSymbol(new PField(NAME_FloorZ, TypeFixed, VARF_Native, myoffsetof(AActor,floorz)));
symt.AddSymbol(new PField(NAME_Health, TypeSInt32, VARF_Native, myoffsetof(AActor,health)));
symt.AddSymbol(new PField(NAME_Mass, TypeSInt32, VARF_Native, myoffsetof(AActor,Mass)));
symt.AddSymbol(new PField(NAME_Pitch, TypeAngle, VARF_Native, myoffsetof(AActor,pitch)));
symt.AddSymbol(new PField(NAME_Roll, TypeAngle, VARF_Native, myoffsetof(AActor,roll)));
symt.AddSymbol(new PField(NAME_Special, TypeSInt32, VARF_Native, myoffsetof(AActor,special)));
symt.AddSymbol(new PField(NAME_TID, TypeSInt32, VARF_Native, myoffsetof(AActor,tid)));
symt.AddSymbol(new PField(NAME_TIDtoHate, TypeSInt32, VARF_Native, myoffsetof(AActor,TIDtoHate)));
symt.AddSymbol(new PField(NAME_WaterLevel, TypeSInt32, VARF_Native, myoffsetof(AActor,waterlevel)));
symt.AddSymbol(new PField(NAME_X, TypeFixed, VARF_Native, myoffsetof(AActor,x)));
symt.AddSymbol(new PField(NAME_Y, TypeFixed, VARF_Native, myoffsetof(AActor,y)));
symt.AddSymbol(new PField(NAME_Z, TypeFixed, VARF_Native, myoffsetof(AActor,z)));
symt.AddSymbol(new PField(NAME_VelX, TypeFixed, VARF_Native, myoffsetof(AActor,velx)));
symt.AddSymbol(new PField(NAME_VelY, TypeFixed, VARF_Native, myoffsetof(AActor,vely)));
symt.AddSymbol(new PField(NAME_VelZ, TypeFixed, VARF_Native, myoffsetof(AActor,velz)));
symt.AddSymbol(new PField(NAME_MomX, TypeFixed, VARF_Native, myoffsetof(AActor,velx)));
symt.AddSymbol(new PField(NAME_MomY, TypeFixed, VARF_Native, myoffsetof(AActor,vely)));
symt.AddSymbol(new PField(NAME_MomZ, TypeFixed, VARF_Native, myoffsetof(AActor,velz)));
symt.AddSymbol(new PField(NAME_ScaleX, TypeFixed, VARF_Native, myoffsetof(AActor,scaleX)));
symt.AddSymbol(new PField(NAME_ScaleY, TypeFixed, VARF_Native, myoffsetof(AActor,scaleY)));
symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor,Score)));
symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor,accuracy)));
symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor,stamina)));
symt.AddSymbol(new PField(NAME_Height, TypeFixed, VARF_Native, myoffsetof(AActor,height)));
symt.AddSymbol(new PField(NAME_Radius, TypeFixed, VARF_Native, myoffsetof(AActor,radius)));
symt.AddSymbol(new PField(NAME_ReactionTime,TypeSInt32, VARF_Native, myoffsetof(AActor,reactiontime)));
symt.AddSymbol(new PField(NAME_MeleeRange, TypeFixed, VARF_Native, myoffsetof(AActor,meleerange)));
symt.AddSymbol(new PField(NAME_Speed, TypeFixed, VARF_Native, myoffsetof(AActor,Speed)));
}
variables.ShrinkToFit();
qsort(&variables[0], variables.Size(), sizeof(variables[0]), varcmp);
}
}

View File

@ -53,43 +53,6 @@
#include "m_fixed.h"
#include "vmbuilder.h"
// Accessible actor member variables
DEFINE_MEMBER_VARIABLE(alpha, AActor)
DEFINE_MEMBER_VARIABLE(angle, AActor)
DEFINE_MEMBER_VARIABLE(args, AActor)
DEFINE_MEMBER_VARIABLE(ceilingz, AActor)
DEFINE_MEMBER_VARIABLE(floorz, AActor)
DEFINE_MEMBER_VARIABLE(health, AActor)
DEFINE_MEMBER_VARIABLE(Mass, AActor)
DEFINE_MEMBER_VARIABLE(pitch, AActor)
DEFINE_MEMBER_VARIABLE(special, AActor)
DEFINE_MEMBER_VARIABLE(special1, AActor)
DEFINE_MEMBER_VARIABLE(special2, AActor)
DEFINE_MEMBER_VARIABLE(tid, AActor)
DEFINE_MEMBER_VARIABLE(TIDtoHate, AActor)
DEFINE_MEMBER_VARIABLE(waterlevel, AActor)
DEFINE_MEMBER_VARIABLE(x, AActor)
DEFINE_MEMBER_VARIABLE(y, AActor)
DEFINE_MEMBER_VARIABLE(z, AActor)
DEFINE_MEMBER_VARIABLE(velx, AActor)
DEFINE_MEMBER_VARIABLE(vely, AActor)
DEFINE_MEMBER_VARIABLE(velz, AActor)
DEFINE_MEMBER_VARIABLE_ALIAS(momx, velx, AActor)
DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor)
DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor)
DEFINE_MEMBER_VARIABLE(scaleX, AActor)
DEFINE_MEMBER_VARIABLE(scaleY, AActor)
//DEFINE_MEMBER_VARIABLE(Damage, AActor)
DEFINE_MEMBER_VARIABLE(Score, AActor)
DEFINE_MEMBER_VARIABLE(accuracy, AActor)
DEFINE_MEMBER_VARIABLE(stamina, AActor)
DEFINE_MEMBER_VARIABLE(height, AActor)
DEFINE_MEMBER_VARIABLE(radius, AActor)
DEFINE_MEMBER_VARIABLE(reactiontime, AActor)
DEFINE_MEMBER_VARIABLE(meleerange, AActor)
DEFINE_MEMBER_VARIABLE(Speed, AActor)
DEFINE_MEMBER_VARIABLE(roll, AActor)
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false)
{
@ -3148,7 +3111,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
else
{
ReturnType = rets[0];
// If more types are added to ParseNativeVariable(), add them here too.
// If more types are added to ParseNativeFunction(), add them here too.
if (rets[0] == TypeSInt32) ValueType = VAL_Int;
else if (rets[0] == TypeFloat64) ValueType = VAL_Float;
else if (rets[0] == TypeAngle) ValueType = VAL_Angle;

View File

@ -391,7 +391,7 @@ static void ParseArgListDef(FScanner &sc, PClassActor *cls,
//==========================================================================
void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
TArray<PType *> &rets, DWORD funcflags, unsigned int error)
TArray<PType *> &rets, DWORD funcflags)
{
assert(cls != NULL);
@ -403,7 +403,7 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
if (afd == NULL)
{
sc.ScriptMessage ("The function '%s' has not been exported from the executable.", funcname.GetChars());
++error;
FScriptPosition::ErrorCounter++;
}
sc.MustGetToken('(');
@ -423,11 +423,7 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
PFunction *sym = new PFunction(funcname);
sym->AddVariant(NewPrototype(rets, args), argflags, *(afd->VMPointer));
sym->Flags = funcflags;
if (error)
{
FScriptPosition::ErrorCounter += error;
}
else if (cls->Symbols.AddSymbol(sym) == NULL)
if (cls->Symbols.AddSymbol(sym) == NULL)
{
delete sym;
sc.ScriptMessage ("'%s' is already defined in class '%s'.",
@ -439,22 +435,20 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
//==========================================================================
//
// ParseNativeVariable
// ParseNativeFunction
//
// Parses a native variable or non-action function declaration.
// Parses a non-action function declaration.
//
//==========================================================================
static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
static void ParseNativeFunction(FScanner &sc, PClassActor *cls)
{
PType *valuetype;
unsigned int error = 0;
TArray<PType *> rets(1);
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
{
sc.ScriptMessage ("variables can only be imported by internal class and actor definitions!");
sc.ScriptMessage ("functions can only be declared by native actors!");
FScriptPosition::ErrorCounter++;
error++;
}
// Read the type and make sure it's int or float.
@ -463,80 +457,33 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *
{
case TK_Int:
case TK_Bool:
valuetype = TypeSInt32;
rets.Push(TypeSInt32);
break;
case TK_Float:
valuetype = TypeFloat64;
rets.Push(TypeFloat64);
break;
case TK_Angle_t:
valuetype = TypeAngle;
rets.Push(TypeAngle);
break;
case TK_Fixed_t:
valuetype = TypeFixed;
rets.Push(TypeFixed);
break;
case TK_Identifier:
valuetype = NULL;
rets.Push(NewPointer(RUNTIME_CLASS(DObject)));
// Todo: Object type
sc.ScriptError("Object type variables not implemented yet!");
break;
default:
sc.ScriptError("Invalid variable type %s", sc.String);
sc.ScriptError("Invalid return type %s", sc.String);
return;
}
sc.MustGetToken(TK_Identifier);
FName symname = sc.String;
if (sc.CheckToken('('))
{
TArray<PType *> rets;
rets.Push(valuetype);
sc.UnGet();
ParseFunctionDef(sc, cls, symname, rets, VARF_Method, error);
return;
}
else
{
if (sc.CheckToken('['))
{
FxExpression *expr = ParseExpression (sc, cls);
if (!expr->isConstant())
{
sc.ScriptError("Array size must be constant");
}
int maxelems = static_cast<FxConstant *>(expr)->GetValue().GetInt();
delete expr;
sc.MustGetToken(']');
valuetype = NewArray(valuetype, maxelems);
}
sc.MustGetToken(';');
const FVariableInfo *vi = FindVariable(symname, cls);
if (vi == NULL)
{
sc.ScriptError("Unknown native variable '%s'", symname.GetChars());
}
PField *sym = new PField(symname, valuetype, VARF_Native);
sym->Offset = (unsigned)vi->address; // todo
if (symt->AddSymbol(sym) == NULL)
{
delete sym;
sc.ScriptMessage ("'%s' is already defined in '%s'.",
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
FScriptPosition::ErrorCounter++;
}
else
{
cls->Fields.Push(sym);
}
}
ParseFunctionDef(sc, cls, sc.String, rets, VARF_Method);
}
//==========================================================================
@ -1089,7 +1036,7 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
{
sc.ScriptMessage ("Action functions can only be imported by internal class and actor definitions!");
++error;
FScriptPosition::ErrorCounter++;
}
sc.MustGetToken(TK_Native);
@ -1100,7 +1047,7 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
}
sc.MustGetToken(TK_Identifier);
funcname = sc.String;
ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action, error);
ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action);
}
//==========================================================================
@ -1239,7 +1186,7 @@ static void ParseActor(FScanner &sc)
break;
case TK_Native:
ParseNativeVariable (sc, &info->Symbols, info);
ParseNativeFunction (sc, info);
break;
case TK_Var:
@ -1366,10 +1313,6 @@ void ParseDecorate (FScanner &sc)
ParseEnum (sc, &GlobalSymbols, NULL);
break;
case TK_Native:
ParseNativeVariable(sc, &GlobalSymbols, NULL);
break;
case ';':
// ';' is the start of a comment in the non-cmode parser which
// is used to parse parts of the DECORATE lump. If we don't add

View File

@ -46,9 +46,6 @@ __declspec(allocate(".creg$z")) void *const CRegTail = 0;
#pragma section(".greg$z",read)
__declspec(allocate(".greg$z")) void *const GRegTail = 0;
#pragma section(".mreg$z",read)
__declspec(allocate(".mreg$z")) void *const MRegTail = 0;
#pragma section(".yreg$z",read)
__declspec(allocate(".yreg$z")) void *const YRegTail = 0;
@ -60,7 +57,6 @@ __declspec(allocate(".yreg$z")) void *const YRegTail = 0;
void *const ARegTail __attribute__((section(SECTION_AREG))) = 0;
void *const CRegTail __attribute__((section(SECTION_CREG))) = 0;
void *const GRegTail __attribute__((section(SECTION_GREG))) = 0;
void *const MRegTail __attribute__((section(SECTION_MREG))) = 0;
void *const YRegTail __attribute__((section(SECTION_YREG))) = 0;
#else

View File

@ -32,47 +32,12 @@ ACTOR Actor native //: Thinker
RipLevelMin 0
RipLevelMax 0
// Variables for the expression evaluator
// NOTE: fixed_t and angle_t are only used here to ensure proper conversion
// Internally they are handled as floats.
// Variables must be native.
native fixed_t alpha;
native angle_t angle;
native int args[5];
native fixed_t ceilingz;
native fixed_t floorz;
native int health;
native int mass;
native angle_t pitch;
native int special;
native int tid;
native int TIDtoHate;
native int waterlevel;
//native int damage;
native fixed_t x;
native fixed_t y;
native fixed_t z;
native fixed_t velx;
native fixed_t vely;
native fixed_t velz;
native fixed_t momx; // alias for velx
native fixed_t momy; // alias for vely
native fixed_t momz; // alias for velz
native fixed_t scaleX;
native fixed_t scaleY;
native int score;
native int accuracy;
native int stamina;
native fixed_t height;
native fixed_t radius;
native int reactiontime;
native fixed_t meleerange;
native fixed_t speed;
native angle_t roll;
// Functions
native bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false);
native bool IsPointerEqual(int ptr_select1, int ptr_select2);
// Action functions
// Meh, MBF redundant functions. Only for DeHackEd support.
action native A_Turn(float angle = 0);
action native A_LineEffect(int boomspecial = 0, int tag = 0);