mirror of https://git.wuffs.org/MWCC
3086 lines
96 KiB
C
3086 lines
96 KiB
C
#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.x4E = 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->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.littleendian) {
|
|
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(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_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(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)->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(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_1 && 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_OVERLOAD));
|
|
|
|
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;
|
|
type->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;
|
|
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);
|
|
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_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:
|
|
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_FLAGS_4)
|
|
CError_Error(CErrorStr329, 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(CErrorStr224);
|
|
}
|
|
if (IsCompleteType(obj->type))
|
|
CInit_DeclareData(obj, NULL, NULL, obj->type->size);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (obj->flags & OBJECT_FLAGS_4)
|
|
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 |= OBJECT_FLAGS_4;
|
|
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_FLAGS_4))
|
|
CInit_DeclareData(list->object, NULL, NULL, list->object->type->size);
|
|
}
|
|
|
|
cinit_tentative = NULL;
|
|
}
|