MWCC/compiler_and_linker/unsorted/CInit.c

3086 lines
95 KiB
C
Raw Normal View History

2022-11-07 03:06:21 +00:00
#include "compiler/CInit.h"
#include "compiler/CABI.h"
#include "compiler/CClass.h"
#include "compiler/CDecl.h"
#include "compiler/CError.h"
2023-01-10 11:05:21 +00:00
#include "compiler/CException.h"
2022-11-07 03:06:21 +00:00
#include "compiler/CExpr.h"
#include "compiler/CInline.h"
#include "compiler/CInt64.h"
#include "compiler/CMachine.h"
#include "compiler/CParser.h"
2023-01-10 11:05:21 +00:00
#include "compiler/CPrec.h"
2022-11-07 03:06:21 +00:00
#include "compiler/CPrep.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/CScope.h"
#include "compiler/CompilerTools.h"
2023-01-10 11:05:21 +00:00
#include "compiler/ObjGenMachO.h"
2022-11-07 03:06:21 +00:00
#include "compiler/objects.h"
#include "compiler/types.h"
TempNodeCB cinit_tempnodefunc;
InitInfo *cinit_initinfo;
static PooledString *cinit_stringlist;
static PooledString *cinit_pooledstringlist;
static PooledString *cinit_pooledwstringlist;
static ObjectList *cinit_tentative;
static TypeClass *cinit_loop_class;
static ENodeList *cinit_fdtnode;
static Boolean cinit_fdtambig;
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct CInit_1C {
struct CInit_1C *next;
Type *type;
ENode *expr;
SInt32 offset;
} CInit_1C;
typedef struct CInit_Stuff {
struct CInit_Stuff *x0;
struct CInit_Stuff *x4;
char *buffer;
SInt32 xC;
SInt32 size;
SInt32 bufferSize;
SInt32 x18;
CInit_1C *x1C;
OLinkList *list;
Boolean flag;
} CInit_Stuff;
typedef enum {
Stage0,
Stage1,
Stage2,
Stage3,
Stage4
} Stage;
typedef struct CInit_Stuff2 {
ENode *expr;
ENode myexpr;
Stage stage;
Boolean x23;
SInt32 x24;
Type *type;
} CInit_Stuff2;
#ifdef __MWERKS__
#pragma options align=reset
#endif
// forward decls
static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean flag);
static void CInit_Type(Type *type, UInt32 qual, Boolean flag);
void CInit_Init(void) {
cinit_tempnodefunc = NULL;
cinit_initinfo = NULL;
cinit_stringlist = NULL;
cinit_pooledstringlist = NULL;
cinit_pooledwstringlist = NULL;
cinit_tentative = NULL;
}
static void CInit_SetupInitInfo(InitInfo *info, Object *obj) {
memclrw(info, sizeof(InitInfo));
info->obj = obj;
info->next = cinit_initinfo;
cinit_initinfo = info;
}
static void CInit_CleanupInitInfo(InitInfo *info) {
cinit_initinfo = info->next;
}
static void CInit_SetupInitInfoBuffer(Type *type) {
SInt32 size = type->size;
cinit_initinfo->size = size;
if (!size)
size = 512;
else if (size & 1)
size++;
cinit_initinfo->buffer = lalloc(size);
cinit_initinfo->bufferSize = size;
memclrw(cinit_initinfo->buffer, size);
}
static void CInit_SetData(void *data, SInt32 offset, SInt32 size) {
SInt32 end;
char *buffer;
end = offset + size;
if (end > cinit_initinfo->size)
cinit_initinfo->size = end;
if (end > cinit_initinfo->bufferSize) {
if (cinit_initinfo->obj->type->size == 0) {
if (end < 8000)
end += 0x400;
else
end += 0x4000;
}
if (end & 1)
end++;
buffer = lalloc(end);
memclrw(buffer, end);
memcpy(buffer, cinit_initinfo->buffer, cinit_initinfo->bufferSize);
cinit_initinfo->buffer = buffer;
cinit_initinfo->bufferSize = end;
}
if (data)
memcpy(cinit_initinfo->buffer + offset, data, size);
}
typedef struct CInit_Initializer {
struct CInit_Initializer *next;
struct CInit_Initializer *sublist;
ENode *expr;
TStreamElement element;
} CInit_Initializer;
static CInit_Initializer *CInit_ParseInitializerList(void) {
CInit_Initializer *r30;
CInit_Initializer *r29;
CInit_Initializer *tmp;
if ((tk = lex()) == '}')
return NULL;
r30 = NULL;
do {
if (r30) {
tmp = lalloc(sizeof(CInit_Initializer));
r29->next = tmp;
r29 = tmp;
}
if (!r30) {
r30 = r29 = lalloc(sizeof(CInit_Initializer));
}
r29->next = NULL;
if (tk == '{') {
r29->element = *CPrep_CurStreamElement();
r29->sublist = CInit_ParseInitializerList();
r29->expr = NULL;
tk = lex();
} else {
r29->sublist = NULL;
r29->expr = conv_assignment_expression();
r29->element = *CPrep_CurStreamElement();
}
if (tk == '}')
return r30;
if (tk != ',') {
CError_Error(116);
return r30;
}
} while ((tk = lex()) != '}');
return r30;
}
static CInit_Initializer *CInit_ParseInitializerClause(void) {
CInit_Initializer *init;
init = lalloc(sizeof(CInit_Initializer));
init->next = NULL;
if (tk != '{') {
init->sublist = NULL;
init->expr = conv_assignment_expression();
init->element = *CPrep_CurStreamElement();
} else {
init->element = *CPrep_CurStreamElement();
init->expr = NULL;
init->sublist = CInit_ParseInitializerList();
tk = lex();
}
return init;
}
static ENode *CInit_ParseInitializer(ENode *expr) {
CInt64 save_int;
Float save_float;
SInt32 save_size;
short t;
switch (tk) {
case TK_INTCONST:
case TK_FLOATCONST:
save_int = tkintconst;
save_float = tkfloatconst;
save_size = tksize;
t = lookahead();
tkintconst = save_int;
tkfloatconst = save_float;
tksize = save_size;
switch (t) {
case ',':
case ';':
case '}':
memclrw(expr, sizeof(ENode));
switch (tk) {
case TK_INTCONST:
expr->type = EINTCONST;
expr->rtype = atomtype();
expr->data.intval = tkintconst;
break;
case TK_FLOATCONST:
expr->type = EFLOATCONST;
expr->rtype = atomtype();
expr->data.floatval = tkfloatconst;
break;
}
tk = lex();
CPrep_TokenStreamFlush();
return expr;
}
}
expr = assignment_expression();
CPrep_TokenStreamFlush();
return expr;
}
static Stage CInit_ParseNextInit(CInit_Stuff2 *s) {
DeclInfo di;
short t;
s->expr = NULL;
if (tk == ';') {
s->stage = Stage4;
return Stage4;
}
switch (s->stage) {
case Stage0:
if (s->x23) {
if (tk == '(') {
tk = lex();
CParser_GetDeclSpecs(&di, 1);
s->type = di.thetype;
if (tk == ')')
tk = lex();
else
CError_Error(115);
if (tk == '(')
tk = lex();
else
CError_Error(114);
s->x24++;
t = lookahead();
if (t == TK_UU_VECTOR || (t == TK_IDENTIFIER && !strcmp("vector", tkidentifier->name)))
CInit_ParseNextInit(s);
s->stage = Stage1;
return Stage1;
}
} else {
if (tk == '{') {
tk = lex();
s->x24 = 0;
s->stage = Stage1;
return Stage1;
}
}
s->expr = CInit_ParseInitializer(&s->myexpr);
s->stage = Stage2;
return Stage2;
case Stage1:
break;
case Stage2:
case Stage3:
if (tk == ',') {
tk = lex();
break;
}
if (s->x24) {
if (tk != ')')
CError_Error(174);
if (s->x24 > 1) {
s->x24--;
tk = lex();
CInit_ParseNextInit(s);
}
} else {
if (tk != '}')
CError_Error(174);
}
s->stage = Stage3;
return Stage3;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(389);
2022-11-07 03:06:21 +00:00
}
switch (tk) {
case '{':
tk = lex();
s->stage = Stage1;
return Stage1;
case '}':
s->stage = Stage3;
return Stage3;
case '(':
if (s->x23) {
tk = lex();
s->stage = Stage1;
return Stage1;
}
case ')':
if (s->x23 && s->x24) {
if (s->x24 > 1) {
s->x24--;
tk = lex();
CInit_ParseNextInit(s);
}
s->stage = Stage3;
return Stage3;
}
default:
s->expr = CInit_ParseInitializer(&s->myexpr);
s->stage = Stage2;
return Stage2;
}
}
static void CInit_CloseInitList(void) {
if (tk == ',' && copts.cplusplus)
tk = lex();
if (tk != '}')
CError_ErrorSkip(130);
else
tk = lex();
}
static Boolean CInit_IsAllZero(char *buf, SInt32 size) {
SInt32 i;
if (copts.explicit_zero_data)
return 0;
for (i = 0; i < size; i++)
if (buf[i]) return 0;
return 1;
}
static Boolean CInit_ClassNeedsConstruction(TypeClass *tclass) {
return CClass_Constructor(tclass) || CClass_Destructor(tclass);
}
static Boolean CInit_IsSimpleStructArrayInit(Type *type) {
switch (type->type) {
case TYPESTRUCT:
return 1;
case TYPEARRAY:
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (!IS_TYPE_CLASS(type))
return 1;
case TYPECLASS:
return !CInit_ClassNeedsConstruction(TYPE_CLASS(type));
default:
return 0;
}
}
static Boolean CInit_IsSimpleInit(Type *type) {
switch (type->type) {
case TYPEPOINTER:
return (TYPE_POINTER(type)->qual & Q_REFERENCE) == 0;
case TYPEARRAY:
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (!IS_TYPE_CLASS(type))
return 1;
case TYPECLASS:
return !CInit_ClassNeedsConstruction(TYPE_CLASS(type));
default:
return 1;
}
}
static Object *CInit_GetInitObject(Object *obj) {
if (obj->datatype == DALIAS) {
2022-12-29 12:32:55 +00:00
CError_ASSERT(521, !obj->u.alias.offset);
2022-11-07 03:06:21 +00:00
obj = obj->u.alias.object;
}
return obj;
}
static Object *CInit_CreateStaticDataObject(Type *type, UInt32 qual, HashNameNode *name) {
Object *obj;
DeclInfo di;
memclrw(&di, sizeof(DeclInfo));
di.thetype = type;
di.name = name ? name : CParser_GetUniqueName();
di.qual = qual;
di.storageclass = TK_STATIC;
di.x4E = 1;
obj = CParser_NewGlobalDataObject(&di);
obj->nspace = cscope_root;
return obj;
}
static Type *CInit_GetRegMemType() {
return CDecl_NewStructType(void_ptr.size * 3, CMach_GetTypeAlign((Type *) &void_ptr));
}
static Object *CInit_CreateStaticData(Type *type) {
Object *obj = CInit_CreateStaticDataObject(type, 0, NULL);
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
return obj;
}
static void CInit_InitNonConst(CInit_Stuff *s, Type *type, ENode *expr) {
CInit_1C *entry;
CInit_1C *scan;
MWVector128 *vec;
if (s->x4->flag || IS_TYPE_VECTOR(type)) {
if (IS_TYPE_VECTOR(type) && ENODE_IS(expr, EVECTOR128CONST)) {
vec = (MWVector128 *) (s->buffer + s->size);
*vec = expr->data.vector128val;
CMach_InitVectorMem(type, *vec, vec, 1);
}
entry = lalloc(sizeof(CInit_1C));
memclrw(entry, sizeof(CInit_1C));
entry->next = NULL;
entry->type = type;
entry->expr = expr;
entry->offset = s->xC + s->size;
if ((scan = s->x4->x1C)) {
while (scan->next)
scan = scan->next;
scan->next = entry;
} else {
s->x4->x1C = entry;
}
} else {
CError_Error(124);
}
}
static CInit_Stuff *CInit_GrowBuffer(CInit_Stuff *s, SInt32 size) {
CInit_Stuff *newbuf;
newbuf = lalloc(sizeof(CInit_Stuff));
memclrw(newbuf, sizeof(CInit_Stuff));
newbuf->x4 = s->x4;
newbuf->buffer = lalloc(size);
newbuf->xC = s->xC + s->size;
newbuf->bufferSize = size;
s->x0 = newbuf;
memset(newbuf->buffer, 0, newbuf->bufferSize);
return newbuf;
}
Boolean CInit_RelocInitCheck(ENode *expr, Object **objptr, CInt64 *valptr, Boolean flag) {
Object *objcheck1;
Object *objcheck2;
CInt64 valcheck1;
CInt64 valcheck2;
*objptr = NULL;
valptr->lo = 0;
valptr->hi = 0;
while (1) {
switch (expr->type) {
case EINTCONST:
*valptr = expr->data.intval;
return 1;
case EOBJREF:
objcheck1 = CInit_GetInitObject(expr->data.objref);
if (objcheck1->datatype == DLOCAL && !flag)
return 0;
*objptr = objcheck1;
return 1;
case ESTRINGCONST:
CInit_RewriteString(expr, 0);
continue;
case ETYPCON:
do {
if (expr->rtype->size != expr->data.monadic->rtype->size)
return 0;
expr = expr->data.monadic;
if (!IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_INT(expr->rtype))
return 0;
} while (ENODE_IS(expr, ETYPCON));
continue;
case EADD:
if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag))
return 0;
if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag))
return 0;
if (objcheck1) {
if (objcheck2)
return 0;
*objptr = objcheck1;
} else {
*objptr = objcheck1;
}
*valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '+', valcheck2);
return 1;
case ESUB:
if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag))
return 0;
if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag))
return 0;
if (objcheck2)
return 0;
*objptr = objcheck1;
*valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '-', valcheck2);
return 1;
default:
return 0;
}
}
}
static void CInit_InitTypePointer(CInit_Stuff *s, ENode *expr, TypePointer *tptr, UInt32 qual) {
Object *obj;
CInt64 val;
OLinkList *list;
expr = CExpr_AssignmentPromotion(expr, TYPE(tptr), qual & (Q_CONST | Q_VOLATILE), 1);
if (IS_TYPE_POINTER_ONLY(expr->rtype) || ENODE_IS(expr, EINTCONST)) {
if (CInit_RelocInitCheck(expr, &obj, &val, 0)) {
if (obj) {
list = lalloc(sizeof(OLinkList));
list->next = s->x4->list;
list->obj = obj;
list->somevalue = CInt64_GetULong(&val);
list->offset = s->xC + s->size;
s->x4->list = list;
} else {
CMach_InitIntMem(TYPE(&stunsignedlong), val, s->buffer + s->size);
}
} else {
CInit_InitNonConst(s, TYPE(tptr), expr);
}
} else {
CError_Error(174);
}
}
static void CInit_InitTypeInt(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) {
expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1);
if (IS_TYPE_INT(expr->rtype)) {
if (ENODE_IS(expr, EINTCONST)) {
CMach_InitIntMem(TYPE(tint), expr->data.intval, s->buffer + s->size);
} else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSI_strict)) {
CInit_InitTypePointer(s, expr->data.monadic, TYPE_POINTER(expr->data.monadic->rtype), qual);
} else {
CInit_InitNonConst(s, TYPE(tint), expr);
}
} else {
CError_Error(174);
}
}
static void CInit_InitTypeFloat(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) {
expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1);
if (IS_TYPE_FLOAT(expr->rtype)) {
if (ENODE_IS(expr, EFLOATCONST)) {
CMach_InitFloatMem(TYPE(tint), expr->data.floatval, s->buffer + s->size);
} else {
CInit_InitNonConst(s, TYPE(tint), expr);
}
} else {
CError_Error(174);
}
}
static void CInit_InitTypeEnum(CInit_Stuff *s, ENode *expr, TypeEnum *tenum, UInt32 qual) {
expr = CExpr_AssignmentPromotion(expr, TYPE(tenum), qual & (Q_CONST | Q_VOLATILE), 1);
if (IS_TYPE_ENUM(expr->rtype)) {
if (ENODE_IS(expr, EINTCONST)) {
CMach_InitIntMem(tenum->enumtype, expr->data.intval, s->buffer + s->size);
} else {
CInit_InitNonConst(s, TYPE(tenum), expr);
}
} else {
CError_Error(174);
}
}
static void CInit_InitTypeMemberPointer(CInit_Stuff *s, ENode *expr, TypeMemberPointer *tmptr, UInt32 qual) {
expr = CExpr_AssignmentPromotion(expr, TYPE(tmptr), qual & (Q_CONST | Q_VOLATILE), 1);
if (ENODE_IS(expr, EINTCONST)) {
CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, s->buffer + s->size);
} else {
CInit_InitNonConst(s, TYPE(tmptr), expr);
}
}
static void CInit_SetBitfield(TypeBitfield *tbitfield, UInt8 *buffer, CInt64 val) {
int i;
int pos;
int step;
if (copts.little_endian) {
pos = tbitfield->unkA;
step = 1;
} else {
pos = tbitfield->unkB + tbitfield->unkA - 1;
step = -1;
}
for (i = 0; i < tbitfield->unkB; i++) {
if (CInt64_GetULong(&val) & 1) {
if (copts.little_endian) {
buffer[pos >> 3] |= 1 << (pos & 7);
} else {
buffer[pos >> 3] |= 0x80 >> (pos & 7);
}
}
val = CInt64_ShrU(val, cint64_one);
pos += step;
}
}
static void CInit_InitTypeBitfield(CInit_Stuff *s, ENode *expr, TypeBitfield *tbitfield, UInt32 qual) {
Type *inner;
inner = tbitfield->bitfieldtype;
if (IS_TYPE_ENUM(inner))
inner = TYPE_ENUM(inner)->enumtype;
expr = CExpr_AssignmentPromotion(expr, inner, qual & (Q_CONST | Q_VOLATILE), 1);
if (IS_TYPE_INT(expr->rtype)) {
if (ENODE_IS(expr, EINTCONST)) {
CInit_SetBitfield(tbitfield, (UInt8 *) s->buffer + s->size, expr->data.intval);
} else {
CInit_InitNonConst(s, TYPE(tbitfield), expr);
}
} else {
CError_Error(174);
}
}
static void CInit_InitTypeArray(CInit_Stuff *s, CInit_Stuff2 *s2, TypePointer *tptr, UInt32 qual, Boolean errorflag) {
SInt32 targetsize;
SInt32 start;
SInt32 i;
Boolean flag;
Boolean is_zero_size;
SInt32 size;
SInt32 tmp;
Boolean is_char_ptr;
Boolean is_wchar_ptr;
is_zero_size = tptr->size == 0;
targetsize = tptr->target->size;
if (!targetsize) {
CError_Error(145);
return;
}
is_char_ptr = IS_TYPE_INT(tptr->target) && (targetsize == 1);
is_wchar_ptr = IS_TYPE_INT(tptr->target) && (targetsize == stwchar.size);
switch (s2->stage) {
case Stage1:
flag = 1;
if (CInit_ParseNextInit(s2) == Stage3) {
if (is_zero_size)
CError_Error(174);
tk = lex();
return;
}
break;
case Stage2:
flag = 0;
break;
}
switch (s2->stage) {
case Stage1:
case Stage2:
break;
default:
CError_Error(174);
return;
}
if (s2->stage == Stage2)
s2->expr = pointer_generation(s2->expr);
if (s2->stage == Stage2 && ENODE_IS(s2->expr, ESTRINGCONST) && (is_char_ptr || is_wchar_ptr)) {
if (IS_TYPE_POINTER_ONLY(s2->expr->rtype) && tptr->target->size != TYPE_POINTER(s2->expr->rtype)->target->size)
CError_Warning(174);
size = tmp = s2->expr->data.string.size;
if (is_zero_size) {
tptr->size = s2->expr->data.string.size;
if (s->bufferSize < tmp)
s = CInit_GrowBuffer(s, tmp);
memcpy(s->buffer, s2->expr->data.string.data, size);
s->size = size;
} else {
if (s2->expr->data.string.size > tptr->size) {
if (copts.cplusplus || (s2->expr->data.string.size - 1) > tptr->size)
CError_Error(147);
s2->expr->data.string.size = tptr->size;
size = tptr->size;
}
memcpy(s->buffer + s->size, s2->expr->data.string.data, size);
}
} else {
if (!flag && errorflag) {
CError_Error(174);
return;
}
start = s->size;
i = 0;
while (1) {
if (is_zero_size) {
size = (i + 1) * targetsize;
s->size = start + size - targetsize - s->xC;
if (s->size + targetsize > s->bufferSize)
s = CInit_GrowBuffer(s, targetsize * 16);
CInit_InitType(s, s2, tptr->target, qual, 0);
tptr->size = size;
s->size = start + size - s->xC;
} else {
if (tptr->size <= i * targetsize) {
i--;
CError_Error(147);
}
s->size = start + i * targetsize;
CInit_InitType(s, s2, tptr->target, qual, 0);
if (!flag && tptr->size <= (i + 1) * targetsize)
break;
}
switch (CInit_ParseNextInit(s2)) {
case Stage1:
case Stage2:
break;
case Stage3:
if (flag)
tk = lex();
return;
default:
CError_Error(130);
return;
}
i++;
}
}
if (flag) {
switch (CInit_ParseNextInit(s2)) {
case Stage3:
tk = lex();
return;
case Stage2:
CError_Error(147);
return;
default:
CError_Error(130);
}
}
}
2023-01-10 11:05:21 +00:00
static void CInit_InitTypeStruct(CInit_Stuff *s, CInit_Stuff2 *s2, const TypeStruct *tstruct, UInt32 qual, Boolean errorflag) {
2022-11-07 03:06:21 +00:00
StructMember *member;
SInt32 start;
Boolean flag;
SInt32 count;
TypePointer arraytype;
MWVector128 *vecp;
int i;
count = 0;
if (s2->type)
tstruct = TYPE_STRUCT(s2->type);
if (!(member = tstruct->members)) {
CError_Error(145);
return;
}
switch (s2->stage) {
case Stage1:
flag = 1;
if (CInit_ParseNextInit(s2) == Stage3) {
tk = lex();
return;
}
break;
case Stage2:
flag = 0;
break;
}
switch (s2->stage) {
case Stage1:
case Stage2:
break;
default:
CError_Error(174);
return;
}
if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tstruct))) {
s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tstruct), qual, 1);
if (IS_TYPE_STRUCT(s2->expr->rtype))
CInit_InitNonConst(s, TYPE(tstruct), s2->expr);
return;
}
start = s->size;
while (1) {
s->size = start + member->offset;
if (!member->type->size) {
if (!errorflag || !IS_TYPE_ARRAY(member->type)) {
CError_Error(147);
if (!IS_TYPE_ARRAY(member->type))
return;
}
arraytype = *TYPE_POINTER(member->type);
CInit_InitTypeArray(s, s2, &arraytype, member->qual, 1);
s->x18 = arraytype.size;
} else {
CInit_InitType(s, s2, member->type, member->qual, 0);
}
count++;
2022-12-29 12:32:55 +00:00
if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr)
CError_ASSERT(1218, !ENODE_IS(s2->expr, EVECTOR128CONST));
2022-11-07 03:06:21 +00:00
do {
member = member->next;
} while (member && (member->qual & Q_OVERLOAD));
if (!member || tstruct->stype == STRUCT_TYPE_UNION) {
if (flag) {
switch (CInit_ParseNextInit(s2)) {
case Stage3:
if (IS_TYPESTRUCT_VECTOR(tstruct)) {
vecp = (MWVector128 *) (s->buffer + start);
CMach_InitVectorMem(TYPE(tstruct), *vecp, vecp, 0);
}
tk = lex();
return;
case Stage2:
CError_Error(147);
return;
default:
CError_Error(130);
return;
}
}
return;
} else {
switch (CInit_ParseNextInit(s2)) {
case Stage1:
case Stage2:
continue;
case Stage3:
if (flag)
tk = lex();
if (IS_TYPESTRUCT_VECTOR(tstruct)) {
switch (TYPE_STRUCT(tstruct)->stype) {
case STRUCT_TYPE_4:
case STRUCT_TYPE_5:
case STRUCT_TYPE_6:
if (count != 16) {
if (count == 1) {
UInt8 val, *p;
p = (UInt8 *) s->buffer;
val = p[0];
for (i = 1; i < 16; i++)
p[i] = val;
} else {
CError_Error(174);
}
}
break;
case STRUCT_TYPE_7:
case STRUCT_TYPE_8:
case STRUCT_TYPE_9:
case STRUCT_TYPE_E:
if (count != 8) {
if (count == 1) {
SInt16 val, *p;
p = (SInt16 *) s->buffer;
val = p[0];
for (i = 1; i < 8; i++)
p[i] = val;
} else {
CError_Error(174);
}
}
break;
case STRUCT_TYPE_A:
case STRUCT_TYPE_B:
case STRUCT_TYPE_C:
case STRUCT_TYPE_D:
if (count != 4) {
if (count == 1) {
UInt32 val, *p;
p = (UInt32 *) s->buffer;
val = p[0];
for (i = 1; i < 4; i++)
p[i] = val;
} else {
CError_Error(174);
}
}
break;
}
}
return;
default:
CError_Error(174);
return;
}
}
}
}
static ObjMemberVar *CInit_FindNextMember(ObjMemberVar *ivar) {
ObjMemberVar *scan = ivar;
while (1) {
scan = scan->next;
if (!scan)
return NULL;
if (!scan->anonunion)
return scan;
if (scan->offset > ivar->offset)
return scan;
if (IS_TYPE_BITFIELD(scan->type) && IS_TYPE_BITFIELD(ivar->type) && TYPE_BITFIELD(scan->type)->unkA != TYPE_BITFIELD(ivar->type)->unkA)
return scan;
}
}
static void CInit_InitTypeClass(CInit_Stuff *s, CInit_Stuff2 *s2, TypeClass *tclass, UInt32 qual, Boolean errorflag) {
ObjMemberVar *ivar;
SInt32 start;
Boolean flag;
SInt32 last_offset;
TypePointer arraytype;
if (tclass->bases || tclass->vtable) {
CError_Error(174);
return;
}
switch (s2->stage) {
case Stage1:
flag = 1;
if (CInit_ParseNextInit(s2) == Stage3) {
tk = lex();
return;
}
break;
case Stage2:
flag = 0;
break;
}
switch (s2->stage) {
case Stage1:
case Stage2:
break;
default:
CError_Error(174);
return;
}
if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tclass) || CExpr_CanImplicitlyConvert(s2->expr, TYPE(tclass), 0))) {
s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tclass), qual, 1);
if (IS_TYPE_CLASS(s2->expr->rtype))
CInit_InitNonConst(s, TYPE(tclass), s2->expr);
return;
}
for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
if (ivar->access != ACCESSPUBLIC) {
CError_Error(174);
break;
}
}
if (!(ivar = tclass->ivars)) {
CError_Error(147);
return;
}
start = s->size;
while (1) {
s->size = start + ivar->offset;
if (!ivar->type->size) {
if (!errorflag || !IS_TYPE_ARRAY(ivar->type)) {
CError_Error(147);
if (!IS_TYPE_ARRAY(ivar->type))
return;
}
arraytype = *TYPE_POINTER(ivar->type);
CInit_InitTypeArray(s, s2, &arraytype, ivar->qual, 1);
s->x18 = arraytype.size;
} else {
CInit_InitType(s, s2, ivar->type, ivar->qual, 0);
}
last_offset = ivar->offset;
if (!(ivar = CInit_FindNextMember(ivar)) || (tclass->mode == CLASS_MODE_1 && ivar->offset == last_offset)) {
if (flag) {
switch (CInit_ParseNextInit(s2)) {
case Stage3:
tk = lex();
return;
case Stage2:
CError_Error(147);
return;
default:
CError_Error(130);
return;
}
}
return;
} else {
switch (CInit_ParseNextInit(s2)) {
case Stage1:
case Stage2:
continue;
case Stage3:
if (flag)
tk = lex();
break;
default:
CError_Error(174);
}
return;
}
}
}
static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean errorflag) {
Boolean flag;
switch (type->type) {
case TYPEVOID:
CError_Error(174);
break;
case TYPEINT:
case TYPEFLOAT:
case TYPEENUM:
case TYPEBITFIELD:
case TYPEMEMBERPOINTER:
case TYPEPOINTER:
switch (s2->stage) {
case Stage1:
flag = 1;
CInit_ParseNextInit(s2);
break;
case Stage2:
flag = 0;
break;
}
if (s2->stage != Stage2) {
CError_Error(174);
return;
}
switch (type->type) {
case TYPEINT:
CInit_InitTypeInt(s, s2->expr, TYPE_INTEGRAL(type), qual);
break;
case TYPEFLOAT:
CInit_InitTypeFloat(s, s2->expr, TYPE_INTEGRAL(type), qual);
break;
case TYPEENUM:
CInit_InitTypeEnum(s, s2->expr, TYPE_ENUM(type), qual);
break;
case TYPEPOINTER:
CInit_InitTypePointer(s, s2->expr, TYPE_POINTER(type), qual);
break;
case TYPEMEMBERPOINTER:
CInit_InitTypeMemberPointer(s, s2->expr, TYPE_MEMBER_POINTER(type), qual);
break;
case TYPEBITFIELD:
CInit_InitTypeBitfield(s, s2->expr, TYPE_BITFIELD(type), qual);
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(1542);
2022-11-07 03:06:21 +00:00
}
if (flag) {
switch (CInit_ParseNextInit(s2)) {
case Stage3:
tk = lex();
break;
case Stage2:
CError_Error(147);
break;
default:
CError_Error(130);
}
}
break;
case TYPESTRUCT:
CInit_InitTypeStruct(s, s2, TYPE_STRUCT(type), qual, errorflag);
break;
case TYPEARRAY:
CInit_InitTypeArray(s, s2, TYPE_POINTER(type), qual, errorflag);
break;
case TYPECLASS:
CInit_InitTypeClass(s, s2, TYPE_CLASS(type), qual, errorflag);
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(1573);
2022-11-07 03:06:21 +00:00
}
}
static void CInit_InitData(CInit_Stuff *s, Type *type, UInt32 qual, Boolean flag) {
CInit_Stuff2 s2;
SInt32 size;
CInit_Stuff *tmp;
char *buffer;
locklheap();
memclrw(s, sizeof(CInit_Stuff));
s->x4 = s;
if (type->size == 0) {
if (IS_TYPE_ARRAY(type))
s->bufferSize = 16 * TYPE_POINTER(type)->target->size;
else
CError_Error(145);
} else {
s->bufferSize = type->size;
}
s->buffer = lalloc(s->bufferSize);
memset(s->buffer, 0, s->bufferSize);
s->flag = flag;
s2.stage = Stage0;
s2.x23 = 0;
if (IS_TYPE_VECTOR(type)) {
s2.x23 = 1;
s->flag = 1;
}
if (IS_TYPE_ARRAY(type) && IS_TYPE_VECTOR(TYPE_POINTER(type)->target)) {
s->flag = 1;
}
s2.type = NULL;
s2.x24 = 0;
CInit_ParseNextInit(&s2);
CInit_InitType(s, &s2, type, qual, 1);
if ((size = type->size + s->x18)) {
if (s->x0) {
buffer = lalloc(size);
for (tmp = s; tmp; tmp = tmp->x0) {
2022-12-29 12:32:55 +00:00
CError_ASSERT(1647, (tmp->xC + tmp->size) <= size);
2022-11-07 03:06:21 +00:00
memcpy(buffer + tmp->xC, tmp->buffer, tmp->size);
}
s->buffer = buffer;
}
} else {
CError_Error(174);
}
s->size = size;
s->x0 = NULL;
unlocklheap();
}
static ENode *CInit_InitConcat(ENode *a1, ENode *a2, SInt32 offset, Type *type, ENode *a5) {
ENode *r30;
ENode *r28;
ENode *tmp;
r28 = lalloc(sizeof(ENode));
*r28 = *a2;
if (offset)
r28 = makediadicnode(r28, intconstnode(TYPE(&stunsignedlong), offset), EADD);
if (IS_TYPE_BITFIELD(type)) {
tmp = makemonadicnode(r28, EBITFIELD);
tmp->rtype = type;
tmp = makemonadicnode(tmp, EINDIRECT);
tmp->rtype = TYPE_BITFIELD(type)->bitfieldtype;
} else {
tmp = makemonadicnode(r28, EINDIRECT);
tmp->rtype = type;
}
r30 = makediadicnode(tmp, a5, EASS);
if (!a1) {
return r30;
} else {
tmp = makediadicnode(a1, r30, ECOMMA);
tmp->rtype = r30->rtype;
return tmp;
}
}
static ENode *CInit_RegisterDtorObject(Type *type, Object *dtor, ENode *objexpr) {
ENode *expr;
if (copts.no_static_dtors)
return objexpr;
expr = lalloc(sizeof(ENode));
expr->type = EFUNCCALL;
expr->cost = 4;
expr->flags = 0;
expr->rtype = CDecl_NewPointerType(type);
expr->data.funccall.funcref = create_objectrefnode(Xgreg_func);
expr->data.funccall.functype = TYPE_FUNC(Xgreg_func->type);
expr->data.funccall.args = lalloc(sizeof(ENodeList));
expr->data.funccall.args->node = objexpr;
expr->data.funccall.args->next = lalloc(sizeof(ENodeList));
2023-01-10 11:05:21 +00:00
expr->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
2022-11-07 03:06:21 +00:00
expr->data.funccall.args->next->next = lalloc(sizeof(ENodeList));
expr->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType()));
expr->data.funccall.args->next->next->next = NULL;
return expr;
}
static Boolean CInit_ConstructGlobalObject(Object *obj, TypeClass *tclass, ENode *valueexpr, SInt32 offset, Boolean flag) {
2023-01-10 11:05:21 +00:00
NameSpaceObjectList *ctor;
2022-11-07 03:06:21 +00:00
Object *dtor;
ENodeList *list;
ENode *expr;
Boolean ctorflag;
ctor = CClass_Constructor(tclass);
dtor = CClass_Destructor(tclass);
if (!ctor && !dtor)
return 0;
if (flag && !ctor && tk == '=' && lookahead() == '{')
return 0;
if (flag && tk == '(') {
tk = lex();
list = CExpr_ScanExpressionList(1);
if (tk == ')')
tk = lex();
else
CError_Error(115);
} else if (valueexpr) {
list = lalloc(sizeof(ENodeList));
list->node = valueexpr;
list->next = NULL;
} else {
list = NULL;
}
expr = create_objectrefnode(obj);
if (offset)
expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD);
if (ctor) {
ctorflag = 1;
if (tk == '=') {
ctorflag = 0;
if (list)
CError_Error(174);
list = lalloc(sizeof(ENodeList));
list->next = NULL;
tk = lex();
list->node = conv_assignment_expression();
}
expr = CExpr_ConstructObject(tclass, expr, list, 0, 1, 0, 1, ctorflag);
if (expr->rtype->type != TYPEPOINTER) {
CError_Error(174);
return 1;
}
} else {
if (list)
CError_Error(174);
}
if (dtor)
expr = CInit_RegisterDtorObject(TYPE(tclass), dtor, expr);
if (cinit_initinfo->x16)
cinit_initinfo->init_expr_register_cb(expr);
else
InitExpr_Register(expr, obj);
return 1;
}
static Boolean CInit_ConstructAutoObject(TypeClass *tclass, ENode *expr, SInt32 offset, Boolean flag) {
ENodeList *r30;
ENode *r29;
2023-01-10 11:05:21 +00:00
NameSpaceObjectList *ctor;
2022-11-07 03:06:21 +00:00
Object *dtor;
Boolean r24;
ctor = CClass_Constructor(tclass);
dtor = CClass_Destructor(tclass);
if (!ctor && !dtor)
return 0;
if (dtor)
CClass_CheckStaticAccess(NULL, tclass, dtor->access);
if (flag && !ctor && tk == '=' && lookahead() == '{')
return 0;
if (flag && tk == '(') {
tk = lex();
r30 = CExpr_ScanExpressionList(1);
if (tk == ')')
tk = lex();
else
CError_Error(115);
} else if (expr) {
r30 = lalloc(sizeof(ENodeList));
r30->node = expr;
r30->next = NULL;
} else {
r30 = NULL;
}
if (ctor) {
r24 = 1;
if (tk == '=') {
if (r30)
CError_Error(174);
r30 = lalloc(sizeof(ENodeList));
r30->next = NULL;
tk = lex();
r30->node = conv_assignment_expression();
r24 = 0;
}
if (!dtor) {
r29 = create_objectrefnode(cinit_initinfo->obj1C);
if (offset)
r29 = makediadicnode(r29, intconstnode(TYPE(&stunsignedlong), offset), EADD);
} else {
r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0);
}
r29 = CExpr_ConstructObject(tclass, r29, r30, 0, 1, 0, 1, r24);
if (!IS_TYPE_POINTER_ONLY(r29->rtype)) {
CError_Error(174);
return 1;
}
r29 = makemonadicnode(r29, EINDIRECT);
r29->rtype = TYPE_POINTER(r29->rtype)->target;
cinit_initinfo->insert_expr_cb(r29);
} else {
if (r30)
CError_Error(174);
if (dtor)
r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0);
cinit_initinfo->insert_expr_cb(r29);
}
return 1;
}
static void CInit_ExprPointer(TypePointer *tptr, ENode *expr) {
Object *obj;
CInt64 val;
OLinkList *list;
if (CInit_RelocInitCheck(expr, &obj, &val, 0)) {
if (obj) {
list = lalloc(sizeof(OLinkList));
list->next = cinit_initinfo->list;
list->obj = obj;
list->somevalue = CInt64_GetULong(&val);
list->offset = cinit_initinfo->expr_offset;
cinit_initinfo->list = list;
} else {
CMach_InitIntMem(TYPE(&stunsignedlong), val, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
}
} else if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(TYPE(tptr), expr, 0);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(124);
}
cinit_initinfo->expr_offset += 4;
}
static void CInit_ExprInt(TypeIntegral *tint, ENode *expr) {
if (ENODE_IS(expr, EINTCONST)) {
CMach_InitIntMem(TYPE(tint), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
} else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSI_strict)) {
CInit_ExprPointer(TYPE_POINTER(expr->data.monadic->rtype), expr->data.monadic);
} else if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(TYPE(tint), expr, 0);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(124);
}
cinit_initinfo->expr_offset += tint->size;
}
static void CInit_ExprFloat(TypeIntegral *tint, ENode *expr) {
if (ENODE_IS(expr, EFLOATCONST)) {
CMach_InitFloatMem(TYPE(tint), expr->data.floatval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
} else if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(TYPE(tint), expr, 0);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(124);
}
cinit_initinfo->expr_offset += tint->size;
}
static void CInit_ExprEnum(TypeEnum *tenum, ENode *expr) {
if (ENODE_IS(expr, EINTCONST)) {
CMach_InitIntMem(tenum->enumtype, expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
} else if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(TYPE(tenum), expr, 0);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(124);
}
cinit_initinfo->expr_offset += tenum->size;
}
static void CInit_ExprMemberPointer(TypeMemberPointer *tmptr, ENode *expr) {
if (ENODE_IS(expr, EINTCONST)) {
CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
} else if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(TYPE(tmptr), expr, 0);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(124);
}
cinit_initinfo->expr_offset += tmptr->size;
}
static void CInit_TypeExpr(Type *type, ENode *expr) {
switch (type->type) {
case TYPEINT:
CInit_ExprInt(TYPE_INTEGRAL(type), expr);
break;
case TYPEFLOAT:
CInit_ExprFloat(TYPE_INTEGRAL(type), expr);
break;
case TYPEENUM:
CInit_ExprEnum(TYPE_ENUM(type), expr);
break;
case TYPEPOINTER:
CInit_ExprPointer(TYPE_POINTER(type), expr);
break;
case TYPEMEMBERPOINTER:
CInit_ExprMemberPointer(TYPE_MEMBER_POINTER(type), expr);
break;
case TYPESTRUCT:
case TYPECLASS:
if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(type, expr, 0);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(124);
}
break;
case TYPEARRAY:
CError_Error(174);
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(2082);
2022-11-07 03:06:21 +00:00
}
}
static void CInit_Bitfield(TypeBitfield *tbitfield) {
Boolean r30;
ENode *expr;
ENode myexpr;
r30 = tk == '{';
if (r30)
tk = lex();
expr = CInit_ParseInitializer(&myexpr);
expr = CExpr_AssignmentPromotion(
expr,
IS_TYPE_ENUM(tbitfield->bitfieldtype) ? TYPE_ENUM(tbitfield->bitfieldtype)->enumtype : tbitfield->bitfieldtype,
0,
1);
if (ENODE_IS(expr, EINTCONST))
CInit_SetBitfield(tbitfield, (UInt8 *) cinit_initinfo->buffer + cinit_initinfo->expr_offset, expr->data.intval);
else
CError_Error(124);
if (r30)
CInit_CloseInitList();
}
static void CInit_Array(TypePointer *tptr, UInt32 qual, Boolean flag) {
SInt32 start;
SInt32 i;
SInt32 targetsize1;
SInt32 targetsize2;
Boolean in_block;
Boolean is_char_ptr;
Boolean needs_construction;
Boolean is_wchar_ptr;
targetsize1 = tptr->target->size;
targetsize2 = tptr->target->size;
if (!tptr->target->size) {
if (!IS_TYPE_ARRAY(tptr->target)) {
CError_Error(145);
return;
}
targetsize1 = tptr->target->size;
targetsize2 = tptr->target->size;
if (!tptr->target->size) {
CError_Error(145);
return;
}
}
is_char_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == 1);
is_wchar_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == stwchar.size);
in_block = 1;
if (flag && !(tk == TK_STRING && is_char_ptr) && !(tk == TK_STRING_WIDE && is_wchar_ptr)) {
if (tk != '{') {
CError_ErrorSkip(135);
return;
}
tk = lex();
} else {
if (tk == '{')
tk = lex();
else
in_block = 0;
}
if ((tk == TK_STRING && is_char_ptr) || (tk == TK_STRING_WIDE && is_wchar_ptr)) {
if (tptr->size) {
if (tksize > tptr->size) {
if (copts.cplusplus || (tksize - (is_wchar_ptr ? stwchar.size : 1)) > tptr->size)
CError_Error(147);
tksize = tptr->size;
}
memcpy(cinit_initinfo->buffer + cinit_initinfo->expr_offset, tkstring, tksize);
} else {
tptr->size = tksize;
CInit_SetData(tkstring, cinit_initinfo->expr_offset, tptr->size);
}
cinit_initinfo->expr_offset += tptr->size;
tk = lex();
if (in_block)
CInit_CloseInitList();
return;
}
if (IS_TYPE_CLASS(tptr->target) && CInit_ClassNeedsConstruction(TYPE_CLASS(tptr->target)))
needs_construction = 1;
else
needs_construction = 0;
start = cinit_initinfo->expr_offset;
i = 0;
while (1) {
if (tk == '}') {
innerloop:
if (tptr->size) {
if (needs_construction) {
while (tptr->size > (i * targetsize1)) {
cinit_initinfo->expr_offset = start + i * targetsize2;
if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(tptr->target, NULL, 1);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(174);
}
i++;
}
}
} else {
tptr->size = i * targetsize1;
}
cinit_initinfo->expr_offset = start + tptr->size;
if (in_block)
tk = lex();
return;
}
if (!tptr->size) {
cinit_initinfo->expr_offset = start + i * targetsize2;
CInit_SetData(NULL, cinit_initinfo->expr_offset, targetsize2);
if (needs_construction) {
if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(174);
}
} else {
CInit_Type(tptr->target, qual, 0);
}
} else {
if (tptr->size <= i * targetsize1) {
i--;
CError_Error(147);
}
cinit_initinfo->expr_offset = start + i * targetsize2;
if (needs_construction) {
if (cinit_initinfo->expr_cb) {
cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1);
cinit_initinfo->expr_cb_called = 1;
} else {
CError_Error(174);
}
} else {
CInit_Type(tptr->target, qual, 0);
}
if (!in_block) {
if (tptr->size <= (i + 1) * targetsize1)
return;
}
}
if (tk != '}') {
if (tk != ',') {
CError_ErrorSkip(121);
in_block = 0;
i++;
goto innerloop;
}
tk = lex();
}
i++;
}
}
static void CInit_Struct(TypeStruct *tstruct, Boolean flag) {
StructMember *member;
SInt32 start;
Boolean in_block;
if (!(member = tstruct->members)) {
CError_Error(145);
return;
}
if (tstruct->stype == STRUCT_TYPE_UNION) {
if (tk == '{') {
tk = lex();
CInit_Type(member->type, member->qual, 0);
if (tk == '}')
tk = lex();
} else {
CInit_Type(member->type, member->qual, 0);
}
return;
}
if (IS_TYPE_VECTOR(tstruct) && tk != '{') {
CInit_TypeExpr(TYPE(tstruct), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tstruct), 0, 1));
return;
}
if (tk != '{') {
if (flag)
CError_ErrorSkip(135);
in_block = 0;
} else {
in_block = 1;
tk = lex();
}
start = cinit_initinfo->expr_offset;
while (1) {
if (tk == '}')
break;
cinit_initinfo->expr_offset = start + member->offset;
if (!member->type->size && IS_TYPE_ARRAY(member->type)) {
CError_Error(147);
break;
}
CInit_Type(member->type, member->qual, 0);
if (tk == '}')
break;
if (tk != ',') {
CError_Error(121);
break;
}
do {
member = member->next;
} while (member && (member->qual & Q_OVERLOAD));
if (!member) {
if (!in_block)
break;
if ((tk = lex()) != '}') {
CError_Error(147);
break;
}
} else {
tk = lex();
}
}
cinit_initinfo->expr_offset = start + tstruct->size;
if (tk == '}' && in_block)
tk = lex();
}
static void CInit_Class(TypeClass *tclass, Boolean flag) {
ObjMemberVar *ivar;
SInt32 start;
Boolean in_block;
if (tk == '{') {
in_block = 1;
tk = lex();
} else {
in_block = 0;
}
if (tclass->bases || tclass->vtable) {
CError_Error(174);
return;
}
for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
if (ivar->access != ACCESSPUBLIC)
break;
}
if (!ivar && !CClass_Constructor(tclass) && (!CClass_Destructor(tclass) || in_block)) {
if ((ivar = tclass->ivars)) {
start = cinit_initinfo->expr_offset;
while (1) {
if (tk == '}')
break;
if (!ivar->type->size && IS_TYPE_ARRAY(ivar->type)) {
CError_Error(147);
break;
}
cinit_initinfo->expr_offset = start + ivar->offset;
CInit_Type(ivar->type, ivar->qual, 0);
if (tk == '}')
break;
if (tk != ',') {
CError_Error(121);
break;
}
do {
ivar = ivar->next;
} while (ivar && ivar->anonunion);
if (!ivar) {
if (!in_block)
break;
if ((tk = lex()) != '}') {
CError_Error(147);
break;
}
} else {
tk = lex();
}
}
} else {
if (in_block && tk != '}')
CError_Error(147);
}
} else {
if (in_block)
CError_Error(174);
CInit_TypeExpr(TYPE(tclass), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tclass), 0, 1));
}
cinit_initinfo->expr_offset = start + tclass->size;
if (tk == '}' && in_block)
tk = lex();
}
static void CInit_Type(Type *type, UInt32 qual, Boolean flag) {
ENode *expr;
ENode myexpr;
switch (type->type) {
case TYPEVOID:
CError_Error(174);
break;
case TYPEINT:
case TYPEFLOAT:
case TYPEENUM:
case TYPEPOINTER:
case TYPEMEMBERPOINTER:
if (tk == '{') {
tk = lex();
expr = CInit_ParseInitializer(&myexpr);
expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1);
CInit_CloseInitList();
} else {
expr = CInit_ParseInitializer(&myexpr);
expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1);
}
CInit_TypeExpr(type, expr);
break;
case TYPEBITFIELD:
CInit_Bitfield(TYPE_BITFIELD(type));
break;
case TYPEARRAY:
CInit_Array(TYPE_POINTER(type), qual, flag);
break;
case TYPESTRUCT:
CInit_Struct(TYPE_STRUCT(type), flag);
break;
case TYPECLASS:
CInit_Class(TYPE_CLASS(type), flag);
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(2482);
2022-11-07 03:06:21 +00:00
}
}
static void CInit_GlobalStaticInit(Type *type, ENode *valueexpr, Boolean flag) {
ENode *expr;
ENode *tmp;
cinit_initinfo->x15 = 1;
if (flag) {
CInit_ConstructGlobalObject(cinit_initinfo->obj, TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0);
} else {
expr = create_objectrefnode(cinit_initinfo->obj);
if (!IS_TYPE_POINTER_ONLY(expr->rtype)) {
CError_Error(174);
return;
}
TYPE_POINTER(expr->rtype)->target = type;
if (cinit_initinfo->expr_offset)
expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD);
tmp = makemonadicnode(expr, EINDIRECT);
tmp->rtype = type;
expr = makediadicnode(tmp, valueexpr, EASS);
if (cinit_initinfo->x16)
cinit_initinfo->init_expr_register_cb(expr);
else
InitExpr_Register(expr, cinit_initinfo->obj);
}
}
static void CInit_AutoInit(Type *type, ENode *valueexpr, Boolean flag) {
ENode *expr;
ENode *tmp;
Type *copy;
SInt32 size;
if (flag) {
CInit_ConstructAutoObject(TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0);
} else {
if (IS_TYPE_ARRAY(type) && (type->size & 1)) {
copy = galloc(sizeof(TypePointer));
*TYPE_POINTER(copy) = *TYPE_POINTER(type);
type = copy;
2023-01-10 11:05:21 +00:00
type->size++;
2022-11-07 03:06:21 +00:00
}
expr = create_objectrefnode(cinit_initinfo->obj1C);
if (!IS_TYPE_POINTER_ONLY(expr->rtype)) {
CError_Error(174);
return;
}
TYPE_POINTER(expr->rtype)->target = type;
if (cinit_initinfo->expr_offset)
expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD);
tmp = makemonadicnode(expr, EINDIRECT);
tmp->rtype = type;
expr = makediadicnode(tmp, valueexpr, EASS);
if (!copts.cplusplus)
CError_Error(124);
cinit_initinfo->insert_expr_cb(expr);
}
}
static SInt32 CInit_AdjustObjectDataSize(Object *obj) {
if (obj->type->size <= 1)
return obj->type->size;
if (obj->type->size & 1)
return obj->type->size + 1;
else
return obj->type->size;
}
static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB expr_cb, Boolean flag) {
Object *r31;
ENode *expr;
ENode *tmpexpr;
Type *inner;
Type *copy;
SInt32 size;
Boolean lastflag;
SInt16 cv;
cinit_initinfo->expr_cb = expr_cb;
expr = NULL;
if (tk == '(') {
if (IS_TYPE_ARRAY(type))
CError_Error(174);
tk = lex();
expr = CExpr_AssignmentPromotion(assignment_expression(), type, qual, 1);
if (tk != ')')
CError_ErrorSkip(115);
else
tk = lex();
goto jump_ahead;
}
tk = lex();
switch (type->type) {
case TYPECLASS:
if (tk == '{' && CClass_Constructor(TYPE_CLASS(type)))
CError_Error(174);
case TYPESTRUCT:
if (tk != '{')
goto generic_type;
case TYPEARRAY:
if (!obj) {
if (IS_TYPE_ARRAY(type)) {
inner = type;
while (IS_TYPE_ARRAY(inner))
inner = TYPE_POINTER(inner)->target;
if (IS_TYPE_CLASS(inner) && CInit_ClassNeedsConstruction(TYPE_CLASS(inner))) {
CInit_SetupInitInfoBuffer(type);
cinit_initinfo->obj = cinit_initinfo->obj1C;
CInit_Type(type, cinit_initinfo->obj->qual, 1);
return 0;
}
if (type->size & 1) {
copy = galloc(sizeof(TypePointer));
*TYPE_POINTER(copy) = *TYPE_POINTER(type);
type = copy;
type->size++;
}
}
obj = CInit_CreateStaticDataObject(type, qual, NULL);
cinit_initinfo->obj = obj;
expr = create_objectnode(obj);
cinit_initinfo->obj1C = obj;
}
CInit_SetupInitInfoBuffer(type);
CInit_Type(type, obj->qual, 1);
2022-12-29 12:32:55 +00:00
CError_ASSERT(2639, obj->type->size == (size = cinit_initinfo->size));
2022-11-07 03:06:21 +00:00
if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, size)) {
CInit_AdjustObjectDataSize(obj);
CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size);
} else {
CInit_AdjustObjectDataSize(obj);
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
}
return expr;
case TYPEINT:
case TYPEFLOAT:
case TYPEENUM:
case TYPEPOINTER:
case TYPEMEMBERPOINTER:
generic_type:
if (obj) {
cv = obj->qual;
cv &= Q_CONST | Q_VOLATILE;
} else {
cv = cinit_initinfo->obj1C->qual;
cv &= Q_CONST | Q_VOLATILE;
}
if (tk == '{') {
tk = lex();
expr = assignment_expression();
CInit_CloseInitList();
} else {
expr = assignment_expression();
}
expr = CExpr_AssignmentPromotion(expr, type, cv, 1);
jump_ahead:
if (obj == NULL)
r31 = cinit_initinfo->obj1C;
else
r31 = obj;
if (is_const_object(r31)) {
switch (r31->type->type) {
case TYPEINT:
case TYPEENUM:
if (ENODE_IS(expr, EINTCONST)) {
r31->u.data.u.intconst = expr->data.intval;
goto common_8068C;
}
break;
case TYPEFLOAT:
if (ENODE_IS(expr, EFLOATCONST)) {
Float fl;
r31->u.data.u.floatconst = galloc(sizeof(Float));
fl = CMach_CalcFloatConvert(r31->type, expr->data.floatval);
*r31->u.data.u.floatconst = fl;
goto common_8068C;
}
break;
case TYPEPOINTER:
tmpexpr = expr;
while (ENODE_IS(tmpexpr, ETYPCON))
tmpexpr = tmpexpr->data.monadic;
if (!ENODE_IS(tmpexpr, EINTCONST))
break;
r31->u.data.u.intconst = tmpexpr->data.intval;
common_8068C:
r31->qual |= Q_10000;
if (!obj) {
r31->sclass = TK_STATIC;
r31->datatype = DDATA;
r31->u.data.linkname = CParser_AppendUniqueName(r31->name->name);
} else if (r31->sclass != TK_STATIC || (r31->flags & OBJECT_FLAGS_2)) {
CInit_ExportConst(r31);
}
return NULL;
}
}
if (!obj || (flag && copts.cplusplus)) {
if (obj) {
IsCompleteType(obj->type);
2022-12-29 12:32:55 +00:00
CError_ASSERT(2747, obj->type->size == type->size);
2022-11-07 03:06:21 +00:00
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
}
return expr;
}
CInit_SetupInitInfoBuffer(type);
CInit_TypeExpr(type, expr);
2022-12-29 12:32:55 +00:00
CError_ASSERT(2756, obj->type->size == cinit_initinfo->size);
2022-11-07 03:06:21 +00:00
IsCompleteType(obj->type);
CInit_AdjustObjectDataSize(obj);
lastflag = !cinit_initinfo->x15 && is_const_object(r31);
if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) {
if (lastflag)
CInit_DeclareReadOnlyData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size);
else
CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size);
} else {
if (lastflag)
CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size);
else
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
}
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(2776);
2022-11-07 03:06:21 +00:00
}
return NULL;
}
void CInit_ExportConst(Object *obj) {
char buffer[64];
if (obj->flags & OBJECT_FLAGS_4)
return;
switch (obj->type->type) {
case TYPEINT:
CMach_InitIntMem(obj->type, obj->u.data.u.intconst, buffer);
break;
case TYPEENUM:
CMach_InitIntMem(TYPE_ENUM(obj->type)->enumtype, obj->u.data.u.intconst, buffer);
break;
case TYPEPOINTER:
CMach_InitIntMem(TYPE(&stunsignedlong), obj->u.data.u.intconst, buffer);
break;
case TYPEFLOAT:
CMach_InitFloatMem(obj->type, *obj->u.data.u.floatconst, buffer);
break;
default:
2022-12-29 12:32:55 +00:00
CError_FATAL(2807);
2022-11-07 03:06:21 +00:00
}
if (is_const_object(obj))
CInit_DeclareReadOnlyData(obj, buffer, NULL, obj->type->size);
else
CInit_DeclareData(obj, buffer, NULL, obj->type->size);
}
static ENode *CInit_ClassInitLoopCallBack(ENode *expr) {
return CExpr_ConstructObject(cinit_loop_class, expr, NULL, 0, 1, 0, 1, 1);
}
Statement *CInit_ConstructClassArray(Statement *stmt, TypeClass *tclass, Object *ctor, Object *dtor, ENode *firstarg, SInt32 count) {
ENode *dtor_expr;
if (stmt)
stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt);
else
stmt = CFunc_AppendStatement(ST_EXPRESSION);
if (dtor)
2023-01-10 11:05:21 +00:00
dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
2022-11-07 03:06:21 +00:00
else
dtor_expr = nullnode();
stmt->expr = CExpr_FuncCallSix(
carr_func,
firstarg,
create_objectrefnode(ctor),
dtor_expr,
intconstnode(TYPE(&stunsignedlong), tclass->size),
intconstnode(TYPE(&stunsignedlong), count),
NULL
);
return stmt;
}
static void CInit_InitializeClassArray(Object *obj, TypeClass *tclass, Boolean flag) {
Object *ctor;
Object *dtor;
SInt32 count;
SInt32 i;
ENode *expr;
SInt32 offset;
ENode *dtor_expr;
Statement *stmt;
TypeFunc *tfunc;
Object *funcobj;
dtor = CClass_Destructor(tclass);
count = obj->type->size / tclass->size;
if (CClass_Constructor(tclass)) {
ctor = CClass_DefaultConstructor(tclass);
if (!ctor) {
ctor = CClass_DummyDefaultConstructor(tclass);
if (!ctor) {
CError_Error(203);
return;
}
}
} else {
ctor = NULL;
}
if (count <= 1 || (!flag && count <= 8)) {
if (flag) {
for (i = 0; i < count; i++) {
CInit_ConstructGlobalObject(obj, tclass, NULL, i * tclass->size, 0);
}
} else {
for (i = 0; i < count; i++) {
offset = i * tclass->size;
expr = create_objectrefnode(obj);
if (offset)
expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD);
if (ctor)
expr = CExpr_ConstructObject(tclass, expr, NULL, 0, 1, 0, 1, 1);
cinit_initinfo->insert_expr_cb(expr);
if (dtor)
CExcept_RegisterDestructorObject(obj, offset, dtor, 1);
}
if (dtor) {
stmt = CFunc_AppendStatement(ST_EXPRESSION);
stmt->expr = nullnode();
}
}
} else {
if (ctor) {
if (!flag && !dtor) {
CInit_ConstructClassArray(NULL, tclass, ctor, dtor, create_objectrefnode(obj), count);
expr = nullnode();
} else {
if (dtor)
2023-01-10 11:05:21 +00:00
dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
2022-11-07 03:06:21 +00:00
else
dtor_expr = nullnode();
expr = CExpr_FuncCallSix(
carr_func,
create_objectrefnode(obj),
create_objectrefnode(ctor),
dtor_expr,
intconstnode(TYPE(&stunsignedlong), tclass->size),
intconstnode(TYPE(&stunsignedlong), count),
NULL
);
}
} else {
expr = nullnode();
}
if (flag) {
if (dtor && !copts.no_static_dtors) {
tfunc = galloc(sizeof(TypeFunc));
memclrw(tfunc, sizeof(TypeFunc));
tfunc->type = TYPEFUNC;
tfunc->functype = &stvoid;
CDecl_SetFuncFlags(tfunc, 1);
funcobj = CParser_NewCompilerDefFunctionObject();
funcobj->name = CParser_AppendUniqueName("__arraydtor");
funcobj->type = TYPE(tfunc);
funcobj->sclass = TK_STATIC;
funcobj->qual = Q_INLINE;
CParser_RegisterSingleExprFunction(funcobj, funccallexpr(
darr_func,
create_objectrefnode(obj),
2023-01-10 11:05:21 +00:00
create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)),
2022-11-07 03:06:21 +00:00
intconstnode(TYPE(&stsignedlong), tclass->size),
intconstnode(TYPE(&stsignedlong), count)
));
expr = makediadicnode(expr, nullnode(), ECOMMA);
expr->rtype = TYPE(&void_ptr);
expr = funccallexpr(
Xgreg_func,
expr,
create_objectrefnode(funcobj),
create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())),
NULL
);
}
if (cinit_initinfo->x16)
cinit_initinfo->init_expr_register_cb(expr);
else
InitExpr_Register(expr, obj);
} else {
stmt = CFunc_AppendStatement(ST_EXPRESSION);
stmt->expr = expr;
if (dtor) {
CExcept_RegisterLocalArray(stmt, obj, dtor, count, tclass->size);
stmt = CFunc_AppendStatement(ST_EXPRESSION);
stmt->expr = nullnode();
}
}
}
}
static ENode *CInit_AutoTempNode(Type *type, Boolean flag) {
ENode *node;
node = CExpr_NewETEMPNode(type, 0);
if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type)))
node->data.temp.needs_dtor = 1;
return node;
}
static ENode *CInit_GlobalTempNode(Type *type, Boolean flag) {
Object *dtor;
ENode *node;
ENode *funcnode;
node = create_objectrefnode(CInit_CreateStaticData(type));
if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type))) && !copts.no_static_dtors) {
if (flag)
CError_Error(190);
funcnode = galloc(sizeof(ENode));
funcnode->type = EFUNCCALL;
funcnode->cost = 200;
funcnode->flags = 0;
funcnode->rtype = CDecl_NewPointerType(type);
funcnode->data.funccall.funcref = create_objectrefnode(Xgreg_func);
funcnode->data.funccall.functype = TYPE_FUNC(Xgreg_func->type);
funcnode->data.funccall.args = lalloc(sizeof(ENodeList));
funcnode->data.funccall.args->node = node;
funcnode->data.funccall.args->next = lalloc(sizeof(ENodeList));
2023-01-10 11:05:21 +00:00
funcnode->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
2022-11-07 03:06:21 +00:00
funcnode->data.funccall.args->next->next = lalloc(sizeof(ENodeList));
funcnode->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType()));;
funcnode->data.funccall.args->next->next->next = NULL;
node = funcnode;
}
return node;
}
static void CInit_RefInit(Type *type, ENode *expr, Boolean flag) {
ENode *objexpr;
objexpr = create_objectrefnode(cinit_initinfo->obj);
if (!IS_TYPE_POINTER_ONLY(objexpr->rtype)) {
CError_Error(174);
return;
}
TYPE_POINTER(objexpr->rtype)->target = type;
if (cinit_initinfo->expr_offset)
objexpr = makediadicnode(objexpr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD);
objexpr = makemonadicnode(objexpr, EINDIRECT);
objexpr->rtype = type;
expr = makediadicnode(objexpr, expr, EASS);
if (cinit_initinfo->x16)
cinit_initinfo->init_expr_register_cb(expr);
else
InitExpr_Register(expr, cinit_initinfo->obj);
}
static Boolean CInit_IsDtorTemp(ENode *expr) {
return ENODE_IS(expr, ETEMP) && expr->data.temp.needs_dtor;
}
static void CInit_FindDtorTemp(ENode *expr) {
ENodeList *list;
while (ENODE_IS(expr, ECOMMA))
expr = expr->data.diadic.right;
if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target)) {
switch (expr->type) {
case ETYPCON:
CInit_FindDtorTemp(expr->data.monadic);
break;
case EADD:
case ESUB:
CInit_FindDtorTemp(expr->data.diadic.left);
CInit_FindDtorTemp(expr->data.diadic.right);
break;
case EFUNCCALL:
case EFUNCCALLP:
if ((list = expr->data.funccall.args)) {
if (CInit_IsDtorTemp(list->node) || ((list = list->next) && CInit_IsDtorTemp(list->node))) {
if (!cinit_fdtnode)
cinit_fdtnode = list;
else
cinit_fdtambig = 1;
}
}
break;
}
}
}
static void CInit_RefTempTransform(Type *type, ENode *expr) {
Object *obj;
2022-12-29 12:32:55 +00:00
CError_ASSERT(3164, IS_TYPE_POINTER_ONLY(type));
2022-11-07 03:06:21 +00:00
if (IS_TYPE_CLASS(TYPE_POINTER(type)->target)) {
cinit_fdtnode = NULL;
cinit_fdtambig = 0;
CInit_FindDtorTemp(expr);
if (cinit_fdtnode) {
2022-12-29 12:32:55 +00:00
CError_ASSERT(3172, !cinit_fdtambig);
2022-11-07 03:06:21 +00:00
obj = create_temp_object(cinit_fdtnode->node->data.temp.type);
cinit_initinfo->register_object_cb(cinit_fdtnode->node->data.temp.type, obj, 0, 0);
cinit_fdtnode->node = create_objectrefnode(obj);
}
}
}
static Boolean CInit_InitReference(Object *obj, Boolean flag) {
ENode *expr;
if (tk == '=') {
cinit_tempnodefunc = flag ? CInit_AutoTempNode : CInit_GlobalTempNode;
tk = lex();
expr = CExpr_AssignmentPromotion(assignment_expression(), obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1);
cinit_tempnodefunc = NULL;
if (flag) {
CInit_RefTempTransform(obj->type, expr);
expr = makediadicnode(create_objectnode2(obj), expr, EASS);
cinit_initinfo->insert_expr_cb(expr);
} else {
cinit_initinfo->expr_cb = CInit_RefInit;
CInit_SetupInitInfoBuffer(obj->type);
CInit_ExprPointer(TYPE_POINTER(obj->type), expr);
2022-12-29 12:32:55 +00:00
CError_ASSERT(3213, obj->type->size == cinit_initinfo->size);
2022-11-07 03:06:21 +00:00
if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) {
IsCompleteType(obj->type);
CInit_AdjustObjectDataSize(obj);
CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size);
} else {
IsCompleteType(obj->type);
CInit_AdjustObjectDataSize(obj);
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
}
}
return 1;
}
return 0;
}
ENode *CInit_AutoObject(Object *obj, Type *type, UInt32 qual) {
CInit_Stuff s;
CInit_1C *entry;
ENode *expr;
ENode *indirect_expr;
ENode *obj_expr;
ENode *const_expr;
Type *newtype;
Object *newobj;
CInit_InitData(&s, type, qual, copts.cplusplus || copts.gcc_extensions || copts.c9x || !obj);
if (!obj && !cscope_currentfunc) {
obj = CParser_NewCompilerDefDataObject();
obj->name = CParser_GetUniqueName();
obj->type = type;
obj->qual = qual;
obj->sclass = TK_STATIC;
CScope_AddGlobalObject(obj);
}
if (IS_TYPE_VECTOR(type) && !s.x1C) {
if (obj)
obj_expr = create_objectrefnode(obj);
else
obj_expr = CExpr_NewETEMPNode(type, 1);
const_expr = CExpr_NewENode(EVECTOR128CONST);
const_expr->rtype = type;
const_expr->data.vector128val = *((MWVector128 *) s.buffer);
indirect_expr = makemonadicnode(obj_expr, EINDIRECT);
indirect_expr->rtype = type;
expr = makediadicnode(indirect_expr, const_expr, EASS);
if (!obj) {
ENode *tmp = lalloc(sizeof(ENode));
*tmp = *obj_expr;
tmp = makemonadicnode(tmp, EINDIRECT);
tmp->rtype = type;
tmp->flags = qual & ENODE_FLAG_QUALS;
expr = makecommaexpression(expr, tmp);
}
return expr;
}
if (s.x18) {
type = CDecl_NewStructType(type->size + s.x18, CMach_GetTypeAlign(type));
if (obj)
obj->type = type;
}
if (obj)
obj_expr = create_objectrefnode(obj);
else
obj_expr = CExpr_NewETEMPNode(type, 1);
newtype = type;
if (IS_TYPE_ARRAY(type))
newtype = CDecl_NewStructType(type->size, CMach_GetTypeAlign(type));
newobj = CInit_CreateStaticDataObject(newtype, 0, NULL);
if (s.list || !CInit_IsAllZero(s.buffer, s.size))
CInit_DeclareReadOnlyData(newobj, s.buffer, s.list, s.size);
else
CInit_DeclareReadOnlyData(newobj, NULL, NULL, s.size);
indirect_expr = makemonadicnode(obj_expr, EINDIRECT);
indirect_expr->rtype = newtype;
expr = makediadicnode(indirect_expr, create_objectnode(newobj), EASS);
for (entry = s.x1C; entry; entry = entry->next) {
expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr);
}
if (!obj) {
ENode *tmp = lalloc(sizeof(ENode));
*tmp = *obj_expr;
tmp = makemonadicnode(tmp, EINDIRECT);
tmp->rtype = type;
tmp->flags = qual & ENODE_FLAG_QUALS;
expr = makecommaexpression(expr, tmp);
} else if (IS_TYPE_ARRAY(type)) {
expr = makecommaexpression(expr, create_objectnode(obj));
}
return expr;
}
static void CInit_GlobalObject(Object *obj) {
CInit_Stuff s;
CInit_1C *entry;
ENode *obj_expr;
ENode *expr;
CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus);
obj_expr = create_objectrefnode(obj);
IsCompleteType(obj->type);
if (!s.x1C && is_const_object(obj))
CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size);
else
CInit_DeclareData(obj, s.buffer, s.list, s.size);
if (s.x1C) {
entry = s.x1C;
expr = NULL;
while (entry) {
if (!ENODE_IS(entry->expr, EVECTOR128CONST))
expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr);
entry = entry->next;
}
if (expr)
InitExpr_Register(expr, obj);
}
}
void CInit_InitializeAutoData(Object *obj, InsertExprCB insert_cb, RegisterObjectCB register_cb) {
ENode *expr;
Type *type;
InitInfo initinfo;
if (CInit_IsSimpleStructArrayInit(obj->type)) {
if (tk == '=' || (tk == '(' && copts.cplusplus)) {
if (tk == '(') {
tk = lex();
expr = conv_assignment_expression();
if (tk != ')')
CError_Error(115);
tk = lex();
} else if (tk == '=' && ((tk = lex()) == '{' || IS_TYPE_ARRAY(obj->type))) {
insert_cb(CInit_AutoObject(obj, obj->type, obj->qual));
return;
} else {
expr = conv_assignment_expression();
}
expr = CExpr_AssignmentPromotion(expr, obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1);
insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS));
} else if (copts.cplusplus && is_const_object(obj)) {
CError_Error(224);
}
return;
}
CInit_SetupInitInfo(&initinfo, obj);
initinfo.obj1C = obj;
initinfo.insert_expr_cb = insert_cb;
initinfo.register_object_cb = register_cb;
if (IS_TYPE_CLASS(obj->type) && CInit_ConstructAutoObject(TYPE_CLASS(obj->type), NULL, 0, 1)) {
CInit_CleanupInitInfo(&initinfo);
return;
}
if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 1)) {
CInit_CleanupInitInfo(&initinfo);
return;
}
if (tk != '=' && (tk != '(' || !copts.cplusplus)) {
if (IS_TYPE_ARRAY(obj->type)) {
type = obj->type;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (IS_TYPE_CLASS(type)) {
if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) {
CInit_InitializeClassArray(obj, TYPE_CLASS(type), 0);
CInit_CleanupInitInfo(&initinfo);
return;
}
CFunc_CheckClassCtors(TYPE_CLASS(type));
}
}
if (IS_TYPE_CLASS(obj->type))
CFunc_CheckClassCtors(TYPE_CLASS(obj->type));
if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus)
CError_Error(224);
} else {
if (obj->type->size || IS_TYPE_ARRAY(obj->type)) {
if ((expr = CInit_GenericData(NULL, obj->type, obj->qual, CInit_AutoInit, 0)))
insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS));
} else {
CError_Error(145);
}
}
if (IS_TYPE_CLASS(obj->type) && CClass_Destructor(TYPE_CLASS(obj->type)))
2023-01-10 11:05:21 +00:00
register_cb(obj->type, obj, 0, 0);
2022-11-07 03:06:21 +00:00
CInit_CleanupInitInfo(&initinfo);
}
void CInit_InitializeStaticData(Object *obj, InitExprRegisterCB cb) {
ENode *expr;
Type *type;
InitInfo initinfo;
CInit_Stuff s;
CInit_1C *entry;
ENode *obj_expr;
if (CInit_IsSimpleStructArrayInit(obj->type)) {
if (tk == '=' || (tk == '(' && copts.cplusplus)) {
if (tk == '=')
tk = lex();
CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus);
IsCompleteType(obj->type);
if (!s.x1C && is_const_object(obj))
CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size);
else
CInit_DeclareData(obj, s.buffer, s.list, s.size);
if (s.x1C) {
obj_expr = create_objectrefnode(obj);
entry = s.x1C;
expr = NULL;
while (entry) {
expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr);
entry = entry->next;
}
cb(expr);
}
} else {
if (copts.cplusplus && is_const_object(obj))
CError_Error(224);
if (is_const_object(obj))
CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size);
else
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
}
return;
}
CInit_SetupInitInfo(&initinfo, obj);
initinfo.x16 = 1;
initinfo.init_expr_register_cb = cb;
if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) {
IsCompleteType(obj->type);
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
CInit_CleanupInitInfo(&initinfo);
return;
}
if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) {
CInit_CleanupInitInfo(&initinfo);
return;
}
if (tk != '=' && (tk != '(' || !copts.cplusplus)) {
if (IsCompleteType(obj->type))
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
if (IS_TYPE_ARRAY(obj->type)) {
type = obj->type;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (IS_TYPE_CLASS(type)) {
if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) {
CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1);
CInit_CleanupInitInfo(&initinfo);
return;
}
CFunc_CheckClassCtors(TYPE_CLASS(type));
}
}
if (IS_TYPE_CLASS(obj->type))
CFunc_CheckClassCtors(TYPE_CLASS(obj->type));
if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus)
CError_Error(224);
} else {
if (obj->type->size || IS_TYPE_ARRAY(obj->type)) {
if ((expr = CInit_GenericData(obj, obj->type, obj->qual, CInit_GlobalStaticInit, 1)))
cb(makediadicnode(create_objectnode2(obj), expr, EASS));
} else {
CError_Error(145);
}
}
CInit_CleanupInitInfo(&initinfo);
}
void CInit_InitializeData(Object *obj) {
Object *dtor;
ObjectList *list;
CInt64 val;
InitInfo initinfo;
Boolean needs_construction;
Type *type;
if (tk == ':') {
tk = lex();
obj->datatype = DABSOLUTE;
val = CExpr_IntegralConstExpr();
obj->u.address = CInt64_GetULong(&val);
return;
}
if (tk != '=' && (tk != '(' || !copts.cplusplus)) {
if (obj->sclass != TK_EXTERN) {
if (!copts.cplusplus) {
if (IsCompleteType(obj->type)) {
for (list = cinit_tentative; list; list = list->next) {
if (list->object == obj)
break;
}
if (!list) {
list = galloc(sizeof(ObjectList));
list->object = obj;
list->next = cinit_tentative;
cinit_tentative = list;
obj->qual |= Q_1000000;
}
}
} else {
if (obj->flags & OBJECT_FLAGS_4)
CError_Error(329, obj);
obj->flags |= OBJECT_FLAGS_4;
needs_construction = 0;
if (IS_TYPE_ARRAY(obj->type)) {
type = obj->type;
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
if (IS_TYPE_CLASS(type)) {
if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) {
CInit_SetupInitInfo(&initinfo, obj);
CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1);
CInit_CleanupInitInfo(&initinfo);
needs_construction = 1;
} else {
CFunc_CheckClassCtors(TYPE_CLASS(type));
}
}
} else {
if (IS_TYPE_CLASS(obj->type)) {
if (CInit_ClassNeedsConstruction(TYPE_CLASS(obj->type))) {
CInit_SetupInitInfo(&initinfo, obj);
CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 0);
CInit_CleanupInitInfo(&initinfo);
needs_construction = 1;
} else {
CFunc_CheckClassCtors(TYPE_CLASS(obj->type));
}
}
}
if (!needs_construction && copts.cplusplus) {
if (IS_TYPE_REFERENCE(obj->type) || is_const_object(obj))
CError_Error(224);
}
if (IsCompleteType(obj->type))
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
}
}
return;
}
if (obj->flags & OBJECT_FLAGS_4)
CError_Error(329, obj);
if (CInit_IsSimpleStructArrayInit(obj->type)) {
if (tk == '=')
tk = lex();
else
CError_Error(121);
CInit_GlobalObject(obj);
return;
}
CInit_SetupInitInfo(&initinfo, obj);
if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) {
IsCompleteType(obj->type);
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
CInit_CleanupInitInfo(&initinfo);
return;
}
if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) {
CInit_CleanupInitInfo(&initinfo);
return;
}
if (obj->type->size == 0 && !IS_TYPE_ARRAY(obj->type)) {
CError_Error(145);
CInit_CleanupInitInfo(&initinfo);
return;
}
if (copts.cplusplus)
CInit_GenericData(obj, obj->type, obj->qual, &CInit_GlobalStaticInit, 0);
else
CInit_GenericData(obj, obj->type, obj->qual, NULL, 0);
if (IS_TYPE_CLASS(obj->type) && (dtor = CClass_Destructor(TYPE_CLASS(obj->type))))
InitExpr_Register(CInit_RegisterDtorObject(obj->type, dtor, create_objectrefnode(obj)), obj);
CInit_CleanupInitInfo(&initinfo);
}
Object *CInit_DeclareString(char *data, SInt32 size, Boolean ispascal, Boolean iswide) {
PooledString *str;
Object *obj;
PooledString *scan;
if (!copts.dont_reuse_strings) {
for (scan = cinit_stringlist; scan; scan = scan->next) {
if (scan->size == size && scan->ispascal == ispascal && scan->iswide == iswide && !memcmp(scan->data, data, size))
return scan->obj;
}
}
obj = CParser_NewCompilerDefDataObject();
obj->name = CParser_GetUniqueName();
if (iswide) {
obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size);
} else {
obj->type = CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size);
}
obj->sclass = TK_STATIC;
CScope_AddGlobalObject(obj);
if (!iswide && !ispascal && size == (strlen(data) + 1))
obj->section = SECT_TEXT_CSTRING;
else
obj->section = SECT_CONST;
if (copts.readonly_strings)
CInit_DeclareReadOnlyData(obj, data, NULL, obj->type->size);
else
CInit_DeclareData(obj, data, NULL, obj->type->size);
str = galloc(sizeof(PooledString));
str->next = cinit_stringlist;
cinit_stringlist = str;
str->obj = obj;
str->offset = 0;
str->size = size;
str->ispascal = ispascal;
str->iswide = iswide;
str->data = galloc(size);
memcpy(str->data, data, size);
return obj;
}
PooledString *CInit_DeclarePooledString(char *data, SInt32 size, Boolean ispascal) {
PooledString *str;
Object *obj;
PooledString *scan;
SInt32 offset;
if (!copts.dont_reuse_strings) {
for (scan = cinit_pooledstringlist; scan; scan = scan->next) {
if (scan->size == size && scan->ispascal == ispascal && !memcmp(scan->data, data, size))
return scan;
}
}
if (cinit_pooledstringlist) {
obj = cinit_pooledstringlist->obj;
offset = cinit_pooledstringlist->offset + cinit_pooledstringlist->size;
} else {
obj = CInit_CreateStaticDataObject(
CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size),
0, GetHashNameNodeExport("@stringBase0"));
obj->section = SECT_CONST;
offset = 0;
}
str = galloc(sizeof(PooledString));
str->next = cinit_pooledstringlist;
cinit_pooledstringlist = str;
str->obj = obj;
str->offset = offset;
str->size = size;
str->ispascal = ispascal;
str->data = galloc(size);
memcpy(str->data, data, size);
return str;
}
PooledString *CInit_DeclarePooledWString(char *data, SInt32 size) {
PooledString *str;
Object *obj;
PooledString *scan;
SInt32 offset;
if (!copts.dont_reuse_strings) {
for (scan = cinit_pooledwstringlist; scan; scan = scan->next) {
if (scan->size == size && !memcmp(scan->data, data, size))
return scan;
}
}
if (cinit_pooledwstringlist) {
obj = cinit_pooledwstringlist->obj;
offset = cinit_pooledwstringlist->offset + cinit_pooledwstringlist->size;
} else {
obj = CInit_CreateStaticDataObject(
CDecl_NewArrayType(CParser_GetWCharType(), size),
0, GetHashNameNodeExport("@wstringBase0"));
obj->section = SECT_CONST;
offset = 0;
}
str = galloc(sizeof(PooledString));
str->next = cinit_pooledwstringlist;
cinit_pooledwstringlist = str;
str->obj = obj;
str->offset = offset;
str->size = size;
str->ispascal = 0;
str->data = galloc(size);
memcpy(str->data, data, size);
return str;
}
void CInit_RewriteString(ENode *expr, Boolean flag) {
PooledString *str;
Boolean is_wide;
if (cparamblkptr->isPrecompiling == 1)
CError_Error(180);
2022-12-29 12:32:55 +00:00
CError_ASSERT(4220, expr->rtype->type == TYPEPOINTER);
2022-11-07 03:06:21 +00:00
is_wide = TYPE_POINTER(expr->rtype)->target->size != 1;
if (copts.pool_strings) {
if (is_wide)
str = CInit_DeclarePooledWString(expr->data.string.data, expr->data.string.size);
else
str = CInit_DeclarePooledString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal);
if (str->offset) {
expr->type = EADD;
expr->data.diadic.right = intconstnode(TYPE(&stunsignedlong), str->offset);
expr->data.diadic.left = create_objectrefnode(str->obj);
expr->cost = 1;
} else {
expr->type = EOBJREF;
expr->data.objref = str->obj;
}
} else {
expr->type = EOBJREF;
expr->data.objref = CInit_DeclareString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal, is_wide);
}
}
void CInit_DeclarePooledStrings(void) {
SInt32 size;
char *buffer;
PooledString *str;
size = 0;
for (str = cinit_pooledstringlist; str; str = str->next)
size += str->size;
if (size) {
cinit_pooledstringlist->obj->type = CDecl_NewArrayType(TYPE(&stchar), size);
buffer = galloc(size);
for (str = cinit_pooledstringlist; str; str = str->next)
memcpy(buffer + str->offset, str->data, str->size);
if (copts.readonly_strings)
CInit_DeclareReadOnlyData(cinit_pooledstringlist->obj, buffer, NULL, size);
else
CInit_DeclareData(cinit_pooledstringlist->obj, buffer, NULL, size);
}
size = 0;
for (str = cinit_pooledwstringlist; str; str = str->next)
size += str->size;
if (size) {
cinit_pooledwstringlist->obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size);
buffer = galloc(size);
for (str = cinit_pooledwstringlist; str; str = str->next)
memcpy(buffer + str->offset, str->data, str->size);
if (copts.readonly_strings)
CInit_DeclareReadOnlyData(cinit_pooledwstringlist->obj, buffer, NULL, size);
else
CInit_DeclareData(cinit_pooledwstringlist->obj, buffer, NULL, size);
}
}
static void declaredata(Object *obj, void *data, OLinkList *list, SInt32 size, Boolean is_readonly) {
OLinkList *scan;
UInt32 qual;
qual = obj->qual;
if (cparamblkptr->isPrecompiling == 1) {
PreComp_StaticData(obj, data, list, size);
} else {
obj->flags |= OBJECT_FLAGS_4;
if (!fatalerrors) {
for (scan = list; scan; scan = scan->next)
CInline_ObjectAddrRef(scan->obj);
if (copts.isGeneratingDebugInfo)
CPrep_SetSourceFile(&cparser_fileoffset);
if (is_readonly)
ObjGen_DeclareReadOnlyData(obj, data, list, size);
else
ObjGen_DeclareData(obj, data, list, size);
obj->qual = qual;
}
}
}
void CInit_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size) {
declaredata(obj, data, list, size, 0);
}
void CInit_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size) {
declaredata(obj, data, list, size, 1);
}
void CInit_DefineTentativeData(void) {
ObjectList *list;
for (list = cinit_tentative; list; list = list->next) {
if (!(list->object->flags & OBJECT_FLAGS_4))
CInit_DeclareData(list->object, NULL, NULL, list->object->type->size);
}
cinit_tentative = NULL;
}