- implemented static constant arrays in class scope.

This commit is contained in:
Christoph Oelckers 2017-03-14 23:52:55 +01:00
parent 93908bc2ef
commit d283beb063
3 changed files with 104 additions and 5 deletions

View file

@ -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);

View file

@ -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

View file

@ -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);