mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-14 08:31:23 +00:00
- process most of the remaining statement types.
- extend assignment operations to handle local variables (untested.) - make the implicit function arguments read only.
This commit is contained in:
parent
24394dfc92
commit
9f99ca4788
8 changed files with 277 additions and 42 deletions
|
@ -500,6 +500,18 @@ int PType::GetLoadOp() const
|
||||||
return OP_NOP;
|
return OP_NOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PType :: GetMoveOp
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int PType::GetMoveOp() const
|
||||||
|
{
|
||||||
|
assert(0 && "Cannot move this type");
|
||||||
|
return OP_NOP;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PType :: GetRegType
|
// PType :: GetRegType
|
||||||
|
@ -974,6 +986,17 @@ int PInt::GetLoadOp() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PInt :: GetLoadOp
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int PInt::GetMoveOp() const
|
||||||
|
{
|
||||||
|
return OP_MOVE;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PInt :: GetRegType
|
// PInt :: GetRegType
|
||||||
|
@ -1271,6 +1294,17 @@ int PFloat::GetLoadOp() const
|
||||||
return OP_NOP;
|
return OP_NOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PFloat :: GetMoveOp
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int PFloat::GetMoveOp() const
|
||||||
|
{
|
||||||
|
return OP_MOVEF;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PFloat :: GetRegType
|
// PFloat :: GetRegType
|
||||||
|
@ -1540,6 +1574,17 @@ int PStatePointer::GetLoadOp() const
|
||||||
return OP_LP;
|
return OP_LP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PStatePointer :: GetMoveOp
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int PStatePointer::GetMoveOp() const
|
||||||
|
{
|
||||||
|
return OP_MOVEA;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PStatePointer :: GetRegType
|
// PStatePointer :: GetRegType
|
||||||
|
@ -1627,6 +1672,17 @@ int PPointer::GetLoadOp() const
|
||||||
return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP;
|
return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PPointer :: GetMoveOp
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int PPointer::GetMoveOp() const
|
||||||
|
{
|
||||||
|
return OP_MOVEA;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PPointer :: GetRegType
|
// PPointer :: GetRegType
|
||||||
|
|
|
@ -28,7 +28,7 @@ enum
|
||||||
VARF_Final = (1<<9), // Function may not be overridden in subclasses
|
VARF_Final = (1<<9), // Function may not be overridden in subclasses
|
||||||
VARF_In = (1<<10),
|
VARF_In = (1<<10),
|
||||||
VARF_Out = (1<<11),
|
VARF_Out = (1<<11),
|
||||||
VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare when checking function signatures)
|
VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare types when checking function signatures)
|
||||||
VARF_Static = (1<<13), // static class data (by necessity read only.)
|
VARF_Static = (1<<13), // static class data (by necessity read only.)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -272,6 +272,9 @@ public:
|
||||||
// Gets the opcode to load from memory to a register
|
// Gets the opcode to load from memory to a register
|
||||||
virtual int GetLoadOp() const;
|
virtual int GetLoadOp() const;
|
||||||
|
|
||||||
|
// Gets the opcode to move from register to another register
|
||||||
|
virtual int GetMoveOp() const;
|
||||||
|
|
||||||
// Gets the register type for this type
|
// Gets the register type for this type
|
||||||
virtual int GetRegType() const;
|
virtual int GetRegType() const;
|
||||||
|
|
||||||
|
@ -409,6 +412,7 @@ public:
|
||||||
virtual double GetValueFloat(void *addr) const;
|
virtual double GetValueFloat(void *addr) const;
|
||||||
virtual int GetStoreOp() const;
|
virtual int GetStoreOp() const;
|
||||||
virtual int GetLoadOp() const;
|
virtual int GetLoadOp() const;
|
||||||
|
virtual int GetMoveOp() const;
|
||||||
virtual int GetRegType() const;
|
virtual int GetRegType() const;
|
||||||
|
|
||||||
bool Unsigned;
|
bool Unsigned;
|
||||||
|
@ -438,6 +442,7 @@ public:
|
||||||
virtual double GetValueFloat(void *addr) const;
|
virtual double GetValueFloat(void *addr) const;
|
||||||
virtual int GetStoreOp() const;
|
virtual int GetStoreOp() const;
|
||||||
virtual int GetLoadOp() const;
|
virtual int GetLoadOp() const;
|
||||||
|
virtual int GetMoveOp() const;
|
||||||
virtual int GetRegType() const;
|
virtual int GetRegType() const;
|
||||||
protected:
|
protected:
|
||||||
PFloat();
|
PFloat();
|
||||||
|
@ -516,6 +521,7 @@ public:
|
||||||
|
|
||||||
virtual int GetStoreOp() const;
|
virtual int GetStoreOp() const;
|
||||||
virtual int GetLoadOp() const;
|
virtual int GetLoadOp() const;
|
||||||
|
virtual int GetMoveOp() const;
|
||||||
virtual int GetRegType() const;
|
virtual int GetRegType() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -530,6 +536,7 @@ public:
|
||||||
|
|
||||||
virtual int GetStoreOp() const;
|
virtual int GetStoreOp() const;
|
||||||
virtual int GetLoadOp() const;
|
virtual int GetLoadOp() const;
|
||||||
|
virtual int GetMoveOp() const;
|
||||||
virtual int GetRegType() const;
|
virtual int GetRegType() const;
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
|
|
|
@ -160,6 +160,18 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name)
|
||||||
|
{
|
||||||
|
if (Block == nullptr)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Block->FindLocalVariable(name, *this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ExpEmit
|
// ExpEmit
|
||||||
|
@ -1611,9 +1623,13 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
|
||||||
int zero = build->GetConstantInt(0);
|
int zero = build->GetConstantInt(0);
|
||||||
int regtype = ValueType->GetRegType();
|
int regtype = ValueType->GetRegType();
|
||||||
ExpEmit pointer = Base->Emit(build);
|
ExpEmit pointer = Base->Emit(build);
|
||||||
|
ExpEmit value = pointer;
|
||||||
|
|
||||||
ExpEmit value(build, regtype);
|
if (!pointer.Target)
|
||||||
|
{
|
||||||
|
value = ExpEmit(build, regtype);
|
||||||
build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero);
|
build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero);
|
||||||
|
}
|
||||||
|
|
||||||
if (regtype == REGT_INT)
|
if (regtype == REGT_INT)
|
||||||
{
|
{
|
||||||
|
@ -1624,7 +1640,10 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
|
||||||
build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, value.RegNum, value.RegNum, build->GetConstantFloat(1.));
|
build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, value.RegNum, value.RegNum, build->GetConstantFloat(1.));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pointer.Target)
|
||||||
|
{
|
||||||
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero);
|
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero);
|
||||||
|
}
|
||||||
|
|
||||||
if (AddressRequested)
|
if (AddressRequested)
|
||||||
{
|
{
|
||||||
|
@ -1690,9 +1709,13 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
|
||||||
int zero = build->GetConstantInt(0);
|
int zero = build->GetConstantInt(0);
|
||||||
int regtype = ValueType->GetRegType();
|
int regtype = ValueType->GetRegType();
|
||||||
ExpEmit pointer = Base->Emit(build);
|
ExpEmit pointer = Base->Emit(build);
|
||||||
|
ExpEmit out = pointer;
|
||||||
|
|
||||||
ExpEmit out(build, regtype);
|
if (!pointer.Target)
|
||||||
|
{
|
||||||
|
out = ExpEmit(build, regtype);
|
||||||
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero);
|
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero);
|
||||||
|
}
|
||||||
|
|
||||||
ExpEmit assign(build, regtype);
|
ExpEmit assign(build, regtype);
|
||||||
if (regtype == REGT_INT)
|
if (regtype == REGT_INT)
|
||||||
|
@ -1704,7 +1727,10 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
|
||||||
build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.));
|
build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pointer.Target)
|
||||||
|
{
|
||||||
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero);
|
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero);
|
||||||
|
}
|
||||||
|
|
||||||
pointer.Free(build);
|
pointer.Free(build);
|
||||||
assign.Free(build);
|
assign.Free(build);
|
||||||
|
@ -1781,6 +1807,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
|
static const BYTE loadops[] = { OP_NOP, OP_LK, OP_LKF, OP_LKS, OP_LKP };
|
||||||
assert(ValueType == Base->ValueType && IsNumeric());
|
assert(ValueType == Base->ValueType && IsNumeric());
|
||||||
assert(ValueType->GetRegType() == Right->ValueType->GetRegType());
|
assert(ValueType->GetRegType() == Right->ValueType->GetRegType());
|
||||||
|
|
||||||
|
@ -1788,16 +1815,31 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
||||||
Address = pointer;
|
Address = pointer;
|
||||||
|
|
||||||
ExpEmit result = Right->Emit(build);
|
ExpEmit result = Right->Emit(build);
|
||||||
|
assert(result.RegType <= REGT_TYPE);
|
||||||
|
|
||||||
|
if (pointer.Target)
|
||||||
|
{
|
||||||
|
if (result.Konst)
|
||||||
|
{
|
||||||
|
build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build->Emit(Right->ValueType->GetMoveOp(), pointer.RegNum, result.RegNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (result.Konst)
|
if (result.Konst)
|
||||||
{
|
{
|
||||||
ExpEmit temp(build, result.RegType);
|
ExpEmit temp(build, result.RegType);
|
||||||
build->Emit(result.RegType == REGT_FLOAT ? OP_LKF : OP_LK, temp.RegNum, result.RegNum);
|
build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum);
|
||||||
result.Free(build);
|
result.Free(build);
|
||||||
result = temp;
|
result = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0));
|
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0));
|
||||||
|
}
|
||||||
|
|
||||||
if (AddressRequested)
|
if (AddressRequested)
|
||||||
{
|
{
|
||||||
|
@ -1837,10 +1879,17 @@ ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
assert(ValueType = Assignment->ValueType);
|
assert(ValueType = Assignment->ValueType);
|
||||||
ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it
|
ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it
|
||||||
|
if (!pointer.Target)
|
||||||
|
{
|
||||||
ExpEmit out(build, ValueType->GetRegType());
|
ExpEmit out(build, ValueType->GetRegType());
|
||||||
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0));
|
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -3858,8 +3907,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
|
||||||
|
// Local variables have highest priority.
|
||||||
|
FxLocalVariableDeclaration *local = ctx.FindLocalVariable(Identifier);
|
||||||
|
if (local != nullptr)
|
||||||
|
{
|
||||||
|
auto x = new FxLocalVariable(local, ScriptPosition);
|
||||||
|
delete this;
|
||||||
|
return x->Resolve(ctx);
|
||||||
|
}
|
||||||
// Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here...
|
// Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here...
|
||||||
|
|
||||||
// see if the current class (if valid) defines something with this name.
|
// see if the current class (if valid) defines something with this name.
|
||||||
PSymbolTable *symtbl;
|
PSymbolTable *symtbl;
|
||||||
if ((sym = ctx.FindInClass(Identifier, symtbl)) != nullptr)
|
if ((sym = ctx.FindInClass(Identifier, symtbl)) != nullptr)
|
||||||
|
@ -3959,6 +4015,40 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptPosition &sc)
|
||||||
|
: FxExpression(sc)
|
||||||
|
{
|
||||||
|
Variable = var;
|
||||||
|
AddressRequested = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx)
|
||||||
|
{
|
||||||
|
CHECKRESOLVED();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FxLocalVariable::RequestAddress(bool *writable)
|
||||||
|
{
|
||||||
|
AddressRequested = true;
|
||||||
|
if (writable != nullptr) *writable = !(Variable->VarFlags & VARF_ReadOnly);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
ExpEmit ret(Variable->RegNum, Variable->ValueType->GetRegType(), false, true);
|
||||||
|
if (AddressRequested) ret.Target = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -3998,9 +4088,7 @@ FxExpression *FxSelf::Resolve(FCompileContext& ctx)
|
||||||
ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// self is always the first pointer passed to the function
|
// self is always the first pointer passed to the function
|
||||||
ExpEmit me(0, REGT_POINTER);
|
return ExpEmit(0, REGT_POINTER, false, true);
|
||||||
me.Fixed = true;
|
|
||||||
return me;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6238,10 +6326,11 @@ ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p)
|
FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p)
|
||||||
:FxExpression(p)
|
:FxExpression(p)
|
||||||
{
|
{
|
||||||
ValueType = type;
|
ValueType = type;
|
||||||
|
VarFlags = varflags;
|
||||||
Name = name;
|
Name = name;
|
||||||
Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false);
|
Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ struct FCompileContext
|
||||||
|
|
||||||
void HandleJumps(int token, FxExpression *handler);
|
void HandleJumps(int token, FxExpression *handler);
|
||||||
void CheckReturn(PPrototype *proto, FScriptPosition &pos);
|
void CheckReturn(PPrototype *proto, FScriptPosition &pos);
|
||||||
|
FxLocalVariableDeclaration *FindLocalVariable(FName name);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -198,7 +199,7 @@ struct ExpEmit
|
||||||
void Free(VMFunctionBuilder *build);
|
void Free(VMFunctionBuilder *build);
|
||||||
void Reuse(VMFunctionBuilder *build);
|
void Reuse(VMFunctionBuilder *build);
|
||||||
|
|
||||||
BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1;
|
BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1, Target:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -964,6 +965,24 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FxLocalVariable
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxLocalVariable : public FxExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FxLocalVariableDeclaration *Variable;
|
||||||
|
bool AddressRequested;
|
||||||
|
|
||||||
|
FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&);
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
bool RequestAddress(bool *writable);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxSelf
|
// FxSelf
|
||||||
|
@ -1382,13 +1401,15 @@ public:
|
||||||
class FxLocalVariableDeclaration : public FxExpression
|
class FxLocalVariableDeclaration : public FxExpression
|
||||||
{
|
{
|
||||||
friend class FxCompoundStatement;
|
friend class FxCompoundStatement;
|
||||||
|
friend class FxLocalVariable;
|
||||||
|
|
||||||
FName Name;
|
FName Name;
|
||||||
FxExpression *Init;
|
FxExpression *Init;
|
||||||
|
int VarFlags;
|
||||||
public:
|
public:
|
||||||
int RegNum = -1;
|
int RegNum = -1;
|
||||||
|
|
||||||
FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p);
|
FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
void Release(VMFunctionBuilder *build);
|
void Release(VMFunctionBuilder *build);
|
||||||
|
|
|
@ -90,7 +90,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
|
||||||
{
|
{
|
||||||
// implied self pointer
|
// implied self pointer
|
||||||
if (args != nullptr) args->Push(NewPointer(cls));
|
if (args != nullptr) args->Push(NewPointer(cls));
|
||||||
if (argflags != nullptr) argflags->Push(VARF_Implicit);
|
if (argflags != nullptr) argflags->Push(VARF_Implicit | VARF_ReadOnly);
|
||||||
if (argnames != nullptr) argnames->Push(NAME_self);
|
if (argnames != nullptr) argnames->Push(NAME_self);
|
||||||
}
|
}
|
||||||
if (funcflags & VARF_Action)
|
if (funcflags & VARF_Action)
|
||||||
|
@ -111,8 +111,8 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
|
||||||
}
|
}
|
||||||
if (argflags != nullptr)
|
if (argflags != nullptr)
|
||||||
{
|
{
|
||||||
argflags->Push(VARF_Implicit);
|
argflags->Push(VARF_Implicit | VARF_ReadOnly);
|
||||||
argflags->Push(VARF_Implicit);
|
argflags->Push(VARF_Implicit | VARF_ReadOnly);
|
||||||
}
|
}
|
||||||
if (argnames != nullptr)
|
if (argnames != nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -693,8 +693,9 @@ void FFunctionBuildList::Build()
|
||||||
{
|
{
|
||||||
auto type = item.Func->Variants[0].Proto->ArgumentTypes[i];
|
auto type = item.Func->Variants[0].Proto->ArgumentTypes[i];
|
||||||
auto name = item.Func->Variants[0].ArgNames[i];
|
auto name = item.Func->Variants[0].ArgNames[i];
|
||||||
// this won't get resolved and won't get emitted. This is only needed so that the code generator can retrieve the necessary info to do its work.
|
auto flags = item.Func->Variants[0].ArgFlags[i];
|
||||||
auto local = new FxLocalVariableDeclaration(type, name, nullptr, FScriptPosition());
|
// this won't get resolved and won't get emitted. It is only needed so that the code generator can retrieve the necessary info about this argument to do its work.
|
||||||
|
auto local = new FxLocalVariableDeclaration(type, name, nullptr, flags, FScriptPosition());
|
||||||
local->RegNum = buildit.Registers[type->GetRegType()].Get(1);
|
local->RegNum = buildit.Registers[type->GetRegType()].Get(1);
|
||||||
ctx.FunctionArgs.Push(local);
|
ctx.FunctionArgs.Push(local);
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ begin:
|
||||||
ASSERTF(a+2); ASSERTA(B); ASSERTKD(C);
|
ASSERTF(a+2); ASSERTA(B); ASSERTKD(C);
|
||||||
GETADDR(PB,KC,X_READ_NIL);
|
GETADDR(PB,KC,X_READ_NIL);
|
||||||
{
|
{
|
||||||
float *v = (float *)ptr;
|
auto v = (double *)ptr;
|
||||||
reg.f[a] = v[0];
|
reg.f[a] = v[0];
|
||||||
reg.f[a+1] = v[1];
|
reg.f[a+1] = v[1];
|
||||||
reg.f[a+2] = v[2];
|
reg.f[a+2] = v[2];
|
||||||
|
@ -204,7 +204,7 @@ begin:
|
||||||
ASSERTF(a+2); ASSERTA(B); ASSERTD(C);
|
ASSERTF(a+2); ASSERTA(B); ASSERTD(C);
|
||||||
GETADDR(PB,RC,X_READ_NIL);
|
GETADDR(PB,RC,X_READ_NIL);
|
||||||
{
|
{
|
||||||
float *v = (float *)ptr;
|
auto v = (double *)ptr;
|
||||||
reg.f[a] = v[0];
|
reg.f[a] = v[0];
|
||||||
reg.f[a+1] = v[1];
|
reg.f[a+1] = v[1];
|
||||||
reg.f[a+2] = v[2];
|
reg.f[a+2] = v[2];
|
||||||
|
@ -290,20 +290,20 @@ begin:
|
||||||
ASSERTA(a); ASSERTF(B+2); ASSERTKD(C);
|
ASSERTA(a); ASSERTF(B+2); ASSERTKD(C);
|
||||||
GETADDR(PA,KC,X_WRITE_NIL);
|
GETADDR(PA,KC,X_WRITE_NIL);
|
||||||
{
|
{
|
||||||
float *v = (float *)ptr;
|
auto v = (double *)ptr;
|
||||||
v[0] = (float)reg.f[B];
|
v[0] = reg.f[B];
|
||||||
v[1] = (float)reg.f[B+1];
|
v[1] = reg.f[B+1];
|
||||||
v[2] = (float)reg.f[B+2];
|
v[2] = reg.f[B+2];
|
||||||
}
|
}
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
OP(SV_R):
|
OP(SV_R):
|
||||||
ASSERTA(a); ASSERTF(B+2); ASSERTD(C);
|
ASSERTA(a); ASSERTF(B+2); ASSERTD(C);
|
||||||
GETADDR(PA,RC,X_WRITE_NIL);
|
GETADDR(PA,RC,X_WRITE_NIL);
|
||||||
{
|
{
|
||||||
float *v = (float *)ptr;
|
auto v = (double *)ptr;
|
||||||
v[0] = (float)reg.f[B];
|
v[0] = reg.f[B];
|
||||||
v[1] = (float)reg.f[B+1];
|
v[1] = reg.f[B+1];
|
||||||
v[2] = (float)reg.f[B+2];
|
v[2] = reg.f[B+2];
|
||||||
}
|
}
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
OP(SBIT):
|
OP(SBIT):
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "m_alloc.h"
|
#include "m_alloc.h"
|
||||||
#include "zcc_parser.h"
|
#include "zcc_parser.h"
|
||||||
|
#include "zcc-parse.h"
|
||||||
#include "zcc_compile.h"
|
#include "zcc_compile.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
|
@ -2344,11 +2345,42 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
// The function name is a simple identifier.
|
// The function name is a simple identifier.
|
||||||
return new FxFunctionCall(static_cast<ZCC_ExprID *>(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast);
|
return new FxFunctionCall(static_cast<ZCC_ExprID *>(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast);
|
||||||
|
|
||||||
|
// not yet done
|
||||||
|
case AST_ExprTypeRef:
|
||||||
|
case AST_SwitchStmt:
|
||||||
|
case AST_CaseStmt:
|
||||||
case AST_ExprMemberAccess:
|
case AST_ExprMemberAccess:
|
||||||
// calling a class member through its pointer
|
// calling a class member through its pointer
|
||||||
// todo.
|
// todo.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AST_AssignStmt:
|
||||||
|
{
|
||||||
|
auto assign = static_cast<ZCC_AssignStmt *>(ast);
|
||||||
|
switch (assign->AssignOp)
|
||||||
|
{
|
||||||
|
case ZCC_EQ:
|
||||||
|
// this ignores multi-assign statements (these should probably be disabled in the grammar.)
|
||||||
|
return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources));
|
||||||
|
|
||||||
|
case ZCC_MULEQ:
|
||||||
|
case ZCC_DIVEQ:
|
||||||
|
case ZCC_MODEQ:
|
||||||
|
case ZCC_ADDEQ:
|
||||||
|
case ZCC_SUBEQ:
|
||||||
|
case ZCC_LSHEQ:
|
||||||
|
case ZCC_RSHEQ:
|
||||||
|
case ZCC_ANDEQ:
|
||||||
|
case ZCC_OREQ:
|
||||||
|
case ZCC_XOREQ:
|
||||||
|
//break;
|
||||||
|
default:
|
||||||
|
Error(ast, "Invalid assign statement");
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AST_ExprBinary:
|
case AST_ExprBinary:
|
||||||
// Array syntax for randoms. They are internally stored as ExprBinary with both an identifier on the left and right side.
|
// Array syntax for randoms. They are internally stored as ExprBinary with both an identifier on the left and right side.
|
||||||
if (fcall->Function->Operation == PEX_ArrayAccess)
|
if (fcall->Function->Operation == PEX_ArrayAccess)
|
||||||
|
@ -2546,7 +2578,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
{
|
{
|
||||||
val = node->Init ? ConvertNode(node->Init) : nullptr;
|
val = node->Init ? ConvertNode(node->Init) : nullptr;
|
||||||
}
|
}
|
||||||
list->Add(new FxLocalVariableDeclaration(type, node->Name, val, *node));
|
list->Add(new FxLocalVariableDeclaration(type, node->Name, val, 0, *node)); // todo: Handle flags in the grammar.
|
||||||
}
|
}
|
||||||
|
|
||||||
node = static_cast<decltype(node)>(node->SiblingNext);
|
node = static_cast<decltype(node)>(node->SiblingNext);
|
||||||
|
@ -2576,6 +2608,35 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_BreakStmt:
|
||||||
|
case AST_ContinueStmt:
|
||||||
|
return new FxJumpStatement(ast->NodeType == AST_BreakStmt ? TK_Break : TK_Continue, *ast);
|
||||||
|
|
||||||
|
case AST_IfStmt:
|
||||||
|
{
|
||||||
|
auto iff = static_cast<ZCC_IfStmt *>(ast);
|
||||||
|
return new FxIfStatement(ConvertNode(iff->Condition), ConvertNode(iff->TruePath), ConvertNode(iff->FalsePath), *ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
case AST_IterationStmt:
|
||||||
|
{
|
||||||
|
auto iter = static_cast<ZCC_IterationStmt *>(ast);
|
||||||
|
if (iter->CheckAt == ZCC_IterationStmt::End)
|
||||||
|
{
|
||||||
|
assert(iter->LoopBumper == nullptr);
|
||||||
|
return new FxDoWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast);
|
||||||
|
}
|
||||||
|
else if (iter->LoopBumper != nullptr)
|
||||||
|
{
|
||||||
|
return new FxForLoop(nullptr, ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopBumper), ConvertNode(iter->LoopStatement), *ast);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new FxWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case AST_CompoundStmt:
|
case AST_CompoundStmt:
|
||||||
{
|
{
|
||||||
auto x = new FxCompoundStatement(*ast);
|
auto x = new FxCompoundStatement(*ast);
|
||||||
|
|
Loading…
Reference in a new issue