summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/C/CInit.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/FrontEnd/C/CInit.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-main.tar.gz
MWCC-main.zip
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CInit.c')
-rw-r--r--compiler_and_linker/FrontEnd/C/CInit.c3082
1 files changed, 3082 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CInit.c b/compiler_and_linker/FrontEnd/C/CInit.c
new file mode 100644
index 0000000..c2d2299
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/C/CInit.c
@@ -0,0 +1,3082 @@
+#include "compiler/CInit.h"
+#include "compiler/CABI.h"
+#include "compiler/CClass.h"
+#include "compiler/CDecl.h"
+#include "compiler/CError.h"
+#include "compiler/CException.h"
+#include "compiler/CExpr.h"
+#include "compiler/CInline.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrec.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/CScope.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/ObjGenMachO.h"
+#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(CErrorStr116);
+ 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(CErrorStr115);
+
+ if (tk == '(')
+ tk = lex();
+ else
+ CError_Error(CErrorStr114);
+ 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(CErrorStr174);
+ if (s->x24 > 1) {
+ s->x24--;
+ tk = lex();
+ CInit_ParseNextInit(s);
+ }
+ } else {
+ if (tk != '}')
+ CError_Error(CErrorStr174);
+ }
+ s->stage = Stage3;
+ return Stage3;
+ default:
+ CError_FATAL(389);
+ }
+
+ 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(CErrorStr130);
+ 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) {
+ CError_ASSERT(521, !obj->u.alias.offset);
+ 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.is_extern_c = 1;
+
+ obj = CParser_NewGlobalDataObject(&di);
+ obj->nspace = cscope_root;
+ return obj;
+}
+
+static Type *CInit_GetRegMemType(void) {
+ 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(CErrorStr124);
+ }
+}
+
+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(CErrorStr174);
+ }
+}
+
+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.ANSIstrict)) {
+ CInit_InitTypePointer(s, expr->data.monadic, TYPE_POINTER(expr->data.monadic->rtype), qual);
+ } else {
+ CInit_InitNonConst(s, TYPE(tint), expr);
+ }
+ } else {
+ CError_Error(CErrorStr174);
+ }
+}
+
+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(CErrorStr174);
+ }
+}
+
+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(CErrorStr174);
+ }
+}
+
+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.littleendian) {
+ pos = tbitfield->offset;
+ step = 1;
+ } else {
+ pos = tbitfield->bitlength + tbitfield->offset - 1;
+ step = -1;
+ }
+ for (i = 0; i < tbitfield->bitlength; i++, pos += step) {
+ if (CInt64_GetULong(&val) & 1) {
+ if (copts.littleendian) {
+ buffer[pos >> 3] |= 1 << (pos & 7);
+ } else {
+ buffer[pos >> 3] |= 0x80 >> (pos & 7);
+ }
+ }
+ val = CInt64_ShrU(val, cint64_one);
+ }
+}
+
+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(CErrorStr174);
+ }
+}
+
+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(CErrorStr145);
+ 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(CErrorStr174);
+ tk = lex();
+ return;
+ }
+ break;
+ case Stage2:
+ flag = 0;
+ break;
+ }
+ switch (s2->stage) {
+ case Stage1:
+ case Stage2:
+ break;
+ default:
+ CError_Error(CErrorStr174);
+ 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(CErrorStr174);
+ 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(CErrorStr147);
+ 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(CErrorStr174);
+ 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(CErrorStr147);
+ }
+ 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(CErrorStr130);
+ return;
+ }
+
+ i++;
+ }
+ }
+
+ if (flag) {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage3:
+ tk = lex();
+ return;
+ case Stage2:
+ CError_Error(CErrorStr147);
+ return;
+ default:
+ CError_Error(CErrorStr130);
+ }
+ }
+}
+
+static void CInit_InitTypeStruct(CInit_Stuff *s, CInit_Stuff2 *s2, const TypeStruct *tstruct, UInt32 qual, Boolean errorflag) {
+ 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(CErrorStr145);
+ 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(CErrorStr174);
+ 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(CErrorStr147);
+ 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++;
+ if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr)
+ CError_ASSERT(1218, !ENODE_IS(s2->expr, EVECTOR128CONST));
+
+ do {
+ member = member->next;
+ } while (member && (member->qual & Q_WEAK));
+
+ 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(CErrorStr147);
+ return;
+ default:
+ CError_Error(CErrorStr130);
+ 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_VECTOR_UCHAR:
+ case STRUCT_VECTOR_SCHAR:
+ case STRUCT_VECTOR_BCHAR:
+ 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(CErrorStr174);
+ }
+ }
+ break;
+ case STRUCT_VECTOR_USHORT:
+ case STRUCT_VECTOR_SSHORT:
+ case STRUCT_VECTOR_BSHORT:
+ case STRUCT_VECTOR_PIXEL:
+ 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(CErrorStr174);
+ }
+ }
+ break;
+ case STRUCT_VECTOR_UINT:
+ case STRUCT_VECTOR_SINT:
+ case STRUCT_VECTOR_BINT:
+ case STRUCT_VECTOR_FLOAT:
+ 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(CErrorStr174);
+ }
+ }
+ break;
+ }
+ }
+ return;
+ default:
+ CError_Error(CErrorStr174);
+ 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)->offset != TYPE_BITFIELD(ivar->type)->offset)
+ 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(CErrorStr174);
+ 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(CErrorStr174);
+ 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(CErrorStr174);
+ break;
+ }
+ }
+
+ if (!(ivar = tclass->ivars)) {
+ CError_Error(CErrorStr147);
+ return;
+ }
+ start = s->size;
+ while (1) {
+ s->size = start + ivar->offset;
+ if (!ivar->type->size) {
+ if (!errorflag || !IS_TYPE_ARRAY(ivar->type)) {
+ CError_Error(CErrorStr147);
+ 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_UNION && ivar->offset == last_offset)) {
+ if (flag) {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage3:
+ tk = lex();
+ return;
+ case Stage2:
+ CError_Error(CErrorStr147);
+ return;
+ default:
+ CError_Error(CErrorStr130);
+ return;
+ }
+ }
+ return;
+ } else {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage1:
+ case Stage2:
+ continue;
+ case Stage3:
+ if (flag)
+ tk = lex();
+ break;
+ default:
+ CError_Error(CErrorStr174);
+ }
+ 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(CErrorStr174);
+ 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(CErrorStr174);
+ 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:
+ CError_FATAL(1542);
+ }
+
+ if (flag) {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage3:
+ tk = lex();
+ break;
+ case Stage2:
+ CError_Error(CErrorStr147);
+ break;
+ default:
+ CError_Error(CErrorStr130);
+ }
+ }
+ 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:
+ CError_FATAL(1573);
+ }
+}
+
+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(CErrorStr145);
+ } 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) {
+ CError_ASSERT(1647, (tmp->xC + tmp->size) <= size);
+ memcpy(buffer + tmp->xC, tmp->buffer, tmp->size);
+ }
+ s->buffer = buffer;
+ }
+ } else {
+ CError_Error(CErrorStr174);
+ }
+
+ 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));
+ expr->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
+ 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) {
+ NameSpaceObjectList *ctor;
+ 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(CErrorStr115);
+ } 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(CErrorStr174);
+
+ 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(CErrorStr174);
+ return 1;
+ }
+ } else {
+ if (list)
+ CError_Error(CErrorStr174);
+ }
+
+ 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;
+ NameSpaceObjectList *ctor;
+ 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(CErrorStr115);
+ } 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(CErrorStr174);
+ 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(CErrorStr174);
+ return 1;
+ }
+ r29 = makemonadicnode(r29, EINDIRECT);
+ r29->rtype = TYPE_POINTER(r29->rtype)->target;
+ cinit_initinfo->insert_expr_cb(r29);
+ } else {
+ if (r30)
+ CError_Error(CErrorStr174);
+ 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(CErrorStr124);
+ }
+
+ 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.ANSIstrict)) {
+ 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(CErrorStr124);
+ }
+
+ 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(CErrorStr124);
+ }
+
+ 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(CErrorStr124);
+ }
+
+ 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(CErrorStr124);
+ }
+
+ 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(CErrorStr124);
+ }
+ break;
+ case TYPEARRAY:
+ CError_Error(CErrorStr174);
+ break;
+ default:
+ CError_FATAL(2082);
+ }
+}
+
+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(CErrorStr124);
+
+ 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(CErrorStr145);
+ return;
+ }
+ targetsize1 = tptr->target->size;
+ targetsize2 = tptr->target->size;
+ if (!tptr->target->size) {
+ CError_Error(CErrorStr145);
+ 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(CErrorStr135);
+ 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(CErrorStr147);
+ 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(CErrorStr174);
+ }
+ 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(CErrorStr174);
+ }
+ } else {
+ CInit_Type(tptr->target, qual, 0);
+ }
+ } else {
+ if (tptr->size <= i * targetsize1) {
+ i--;
+ CError_Error(CErrorStr147);
+ }
+
+ 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(CErrorStr174);
+ }
+ } else {
+ CInit_Type(tptr->target, qual, 0);
+ }
+
+ if (!in_block) {
+ if (tptr->size <= (i + 1) * targetsize1)
+ return;
+ }
+ }
+
+ if (tk != '}') {
+ if (tk != ',') {
+ CError_ErrorSkip(CErrorStr121);
+ 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(CErrorStr145);
+ 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(CErrorStr135);
+ 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(CErrorStr147);
+ break;
+ }
+
+ CInit_Type(member->type, member->qual, 0);
+ if (tk == '}')
+ break;
+
+ if (tk != ',') {
+ CError_Error(CErrorStr121);
+ break;
+ }
+
+ do {
+ member = member->next;
+ } while (member && (member->qual & Q_WEAK));
+
+ if (!member) {
+ if (!in_block)
+ break;
+ if ((tk = lex()) != '}') {
+ CError_Error(CErrorStr147);
+ 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(CErrorStr174);
+ 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(CErrorStr147);
+ break;
+ }
+
+ cinit_initinfo->expr_offset = start + ivar->offset;
+ CInit_Type(ivar->type, ivar->qual, 0);
+
+ if (tk == '}')
+ break;
+
+ if (tk != ',') {
+ CError_Error(CErrorStr121);
+ break;
+ }
+
+ do {
+ ivar = ivar->next;
+ } while (ivar && ivar->anonunion);
+
+ if (!ivar) {
+ if (!in_block)
+ break;
+ if ((tk = lex()) != '}') {
+ CError_Error(CErrorStr147);
+ break;
+ }
+ } else {
+ tk = lex();
+ }
+ }
+ } else {
+ if (in_block && tk != '}')
+ CError_Error(CErrorStr147);
+ }
+ } else {
+ if (in_block)
+ CError_Error(CErrorStr174);
+ 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(CErrorStr174);
+ 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:
+ CError_FATAL(2482);
+ }
+}
+
+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(CErrorStr174);
+ 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;
+ copy->size++;
+ }
+ expr = create_objectrefnode(cinit_initinfo->obj1C);
+ if (!IS_TYPE_POINTER_ONLY(expr->rtype)) {
+ CError_Error(CErrorStr174);
+ 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(CErrorStr124);
+ 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(CErrorStr174);
+ tk = lex();
+ expr = CExpr_AssignmentPromotion(assignment_expression(), type, qual, 1);
+ if (tk != ')')
+ CError_ErrorSkip(CErrorStr115);
+ else
+ tk = lex();
+ goto jump_ahead;
+ }
+
+ tk = lex();
+ switch (type->type) {
+ case TYPECLASS:
+ if (tk == '{' && CClass_Constructor(TYPE_CLASS(type)))
+ CError_Error(CErrorStr174);
+ 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);
+ CError_ASSERT(2639, obj->type->size == (size = cinit_initinfo->size));
+ 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 & Q_CV;
+ else
+ cv = cinit_initinfo->obj1C->qual & Q_CV;
+
+ 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_INLINE_DATA;
+ 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);
+ CError_ASSERT(2747, obj->type->size == type->size);
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ }
+ return expr;
+ }
+
+ CInit_SetupInitInfoBuffer(type);
+ CInit_TypeExpr(type, expr);
+ CError_ASSERT(2756, obj->type->size == cinit_initinfo->size);
+
+ 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:
+ CError_FATAL(2776);
+ }
+
+ return NULL;
+}
+
+void CInit_ExportConst(Object *obj) {
+ char buffer[64];
+
+ if (obj->flags & OBJECT_DEFINED)
+ 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:
+ CError_FATAL(2807);
+ }
+
+ 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)
+ dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
+ 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(CErrorStr203);
+ 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)
+ dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
+ 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),
+ create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)),
+ 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(CErrorStr190);
+
+ 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));
+ funcnode->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1));
+ 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(CErrorStr174);
+ 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;
+
+ CError_ASSERT(3164, IS_TYPE_POINTER_ONLY(type));
+
+ if (IS_TYPE_CLASS(TYPE_POINTER(type)->target)) {
+ cinit_fdtnode = NULL;
+ cinit_fdtambig = 0;
+ CInit_FindDtorTemp(expr);
+ if (cinit_fdtnode) {
+ CError_ASSERT(3172, !cinit_fdtambig);
+ 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);
+ CError_ASSERT(3213, obj->type->size == cinit_initinfo->size);
+
+ 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(CErrorStr115);
+ 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(CErrorStr224);
+ }
+
+ 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(CErrorStr224);
+ } 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(CErrorStr145);
+ }
+ }
+
+ if (IS_TYPE_CLASS(obj->type) && CClass_Destructor(TYPE_CLASS(obj->type)))
+ register_cb(obj->type, obj, 0, 0);
+
+ 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(CErrorStr224);
+
+ 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(CErrorStr224);
+ } 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(CErrorStr145);
+ }
+ }
+
+ 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_DEFINED)
+ CError_Error(CErrorStr329, obj);
+ obj->flags = obj->flags | OBJECT_DEFINED;
+
+ 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(CErrorStr224);
+ }
+ if (IsCompleteType(obj->type))
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ }
+ }
+ return;
+ }
+
+ if (obj->flags & OBJECT_DEFINED)
+ CError_Error(CErrorStr329, obj);
+
+ if (CInit_IsSimpleStructArrayInit(obj->type)) {
+ if (tk == '=')
+ tk = lex();
+ else
+ CError_Error(CErrorStr121);
+ 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(CErrorStr145);
+ 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->precompile == 1)
+ CError_Error(CErrorStr180);
+
+ CError_ASSERT(4220, expr->rtype->type == TYPEPOINTER);
+
+ is_wide = TYPE_POINTER(expr->rtype)->target->size != 1;
+ if (copts.poolstrings) {
+ 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->precompile == 1) {
+ PreComp_StaticData(obj, data, list, size);
+ } else {
+ obj->flags = obj->flags | OBJECT_DEFINED;
+ if (!fatalerrors) {
+ for (scan = list; scan; scan = scan->next)
+ CInline_ObjectAddrRef(scan->obj);
+ if (copts.filesyminfo)
+ 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_DEFINED))
+ CInit_DeclareData(list->object, NULL, NULL, list->object->type->size);
+ }
+
+ cinit_tentative = NULL;
+}