mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- implemented static constant arrays in class scope.
This commit is contained in:
parent
93908bc2ef
commit
d283beb063
3 changed files with 104 additions and 5 deletions
|
@ -6292,9 +6292,19 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Unable to access '%s.%s' in a static context\n", ccls->TypeName.GetChars(), Identifier.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
auto f = dyn_cast<PField>(sym);
|
||||
if (f != nullptr && (f->Flags & VARF_Static | VARF_ReadOnly) == (VARF_Static | VARF_ReadOnly))
|
||||
{
|
||||
auto x = new FxGlobalVariable(f, ScriptPosition);
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Unable to access '%s.%s' in a static context\n", ccls->TypeName.GetChars(), Identifier.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6933,6 +6943,15 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
BarrierSide = pmember->BarrierSide;
|
||||
}
|
||||
|
||||
// Even though this is global, static and readonly, we still need to do the scope checks for consistency.
|
||||
if ((membervar->Flags & (VARF_Static | VARF_ReadOnly)) == (VARF_Static | VARF_ReadOnly))
|
||||
{
|
||||
// This is a static constant array, which is stored at a constant address, like a global variable.
|
||||
auto x = new FxGlobalVariable(membervar, ScriptPosition);
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType);
|
||||
|
|
|
@ -198,7 +198,10 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
|
|||
break;
|
||||
|
||||
case AST_StaticArrayStatement:
|
||||
cls->Arrays.Push(static_cast<ZCC_StaticArrayStatement *>(node));
|
||||
if (AddTreeNode(static_cast<ZCC_StaticArrayStatement *>(node)->Id, node, &cls->TreeNodes))
|
||||
{
|
||||
cls->Arrays.Push(static_cast<ZCC_StaticArrayStatement *>(node));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -265,7 +268,10 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC
|
|||
break;
|
||||
|
||||
case AST_StaticArrayStatement:
|
||||
cls->Arrays.Push(static_cast<ZCC_StaticArrayStatement *>(node));
|
||||
if (AddTreeNode(static_cast<ZCC_StaticArrayStatement *>(node)->Id, node, &cls->TreeNodes))
|
||||
{
|
||||
cls->Arrays.Push(static_cast<ZCC_StaticArrayStatement *>(node));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -826,6 +832,16 @@ void ZCCCompiler::CompileAllConstants()
|
|||
{
|
||||
Error(constantwork[i].node, "%s is not a constant", FName(constantwork[i].node->NodeName).GetChars());
|
||||
}
|
||||
|
||||
|
||||
for (auto s : Structs)
|
||||
{
|
||||
CompileArrays(s);
|
||||
}
|
||||
for (auto c : Classes)
|
||||
{
|
||||
CompileArrays(c);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -942,6 +958,69 @@ bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work)
|
|||
}
|
||||
|
||||
|
||||
void ZCCCompiler::CompileArrays(ZCC_StructWork *work)
|
||||
{
|
||||
for(auto sas : work->Arrays)
|
||||
{
|
||||
PType *ztype = DetermineType(work->Type(), sas, sas->Id, sas->Type, false, true);
|
||||
PType *ctype = ztype;
|
||||
FArgumentList values;
|
||||
|
||||
// Don't use narrow typea for casting.
|
||||
if (ctype->IsA(RUNTIME_CLASS(PInt))) ctype = static_cast<PInt*>(ztype)->Unsigned ? TypeUInt32 : TypeSInt32;
|
||||
else if (ctype == TypeFloat32) ctype = TypeFloat64;
|
||||
|
||||
ConvertNodeList(values, sas->Values);
|
||||
|
||||
bool fail = false;
|
||||
FCompileContext ctx(OutNamespace, work->Type(), false);
|
||||
|
||||
char *destmem = (char *)ClassDataAllocator.Alloc(values.Size() * ztype->Align);
|
||||
memset(destmem, 0, values.Size() * ztype->Align);
|
||||
char *copyp = destmem;
|
||||
for (unsigned i = 0; i < values.Size(); i++)
|
||||
{
|
||||
values[i] = new FxTypeCast(values[i], ctype, false);
|
||||
values[i] = values[i]->Resolve(ctx);
|
||||
if (values[i] == nullptr) fail = true;
|
||||
else if (!values[i]->isConstant())
|
||||
{
|
||||
Error(sas, "Initializer must be constant");
|
||||
fail = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpVal val = static_cast<FxConstant*>(values[i])->GetValue();
|
||||
switch (ztype->GetRegType())
|
||||
{
|
||||
default:
|
||||
// should never happen
|
||||
Error(sas, "Non-integral type in constant array");
|
||||
return;
|
||||
|
||||
case REGT_INT:
|
||||
ztype->SetValue(copyp, val.GetInt());
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
ztype->SetValue(copyp, val.GetFloat());
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
*(void**)copyp = val.GetPointer();
|
||||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
::new(copyp) FString(val.GetString());
|
||||
break;
|
||||
}
|
||||
copyp += ztype->Align;
|
||||
}
|
||||
}
|
||||
work->Type()->Symbols.AddSymbol(new PField(sas->Id, NewArray(ztype, values.Size()), VARF_Static | VARF_ReadOnly, (size_t)destmem));
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ZCCCompiler :: NodeFromSymbol
|
||||
|
|
|
@ -102,6 +102,7 @@ private:
|
|||
void CompileAllConstants();
|
||||
void AddConstant(ZCC_ConstantWork &constant);
|
||||
bool CompileConstant(ZCC_ConstantWork *def);
|
||||
void CompileArrays(ZCC_StructWork *work);
|
||||
|
||||
void CompileAllFields();
|
||||
bool CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false);
|
||||
|
|
Loading…
Reference in a new issue