summaryrefslogtreecommitdiff
path: root/compiler_and_linker
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2022-11-07 03:06:21 +0000
committerAsh Wolf <ninji@wuffs.org>2022-11-07 03:06:21 +0000
commit9a46dd0e2e80790d9848c0bbd718932a27c23269 (patch)
treee7a8e976c7138d50a69ff4778c4e8572efd94452 /compiler_and_linker
parentd0b9848c54e6f85ab713f059dcd1ddef7e57caa6 (diff)
downloadMWCC-9a46dd0e2e80790d9848c0bbd718932a27c23269.tar.gz
MWCC-9a46dd0e2e80790d9848c0bbd718932a27c23269.zip
honk
Diffstat (limited to 'compiler_and_linker')
-rw-r--r--compiler_and_linker/FrontEnd/C/CPrep.c2984
-rw-r--r--compiler_and_linker/FrontEnd/C/CPrepTokenizer.c1941
-rw-r--r--compiler_and_linker/FrontEnd/C/CScope.c22
-rw-r--r--compiler_and_linker/unsorted/CABI.c93
-rw-r--r--compiler_and_linker/unsorted/CClass.c122
-rw-r--r--compiler_and_linker/unsorted/CCompiler.c9
-rw-r--r--compiler_and_linker/unsorted/CDecl.c4902
-rw-r--r--compiler_and_linker/unsorted/CExpr.c123
-rw-r--r--compiler_and_linker/unsorted/CExpr2.c1934
-rw-r--r--compiler_and_linker/unsorted/CFunc.c105
-rw-r--r--compiler_and_linker/unsorted/CInit.c3107
-rw-r--r--compiler_and_linker/unsorted/CInline.c116
-rw-r--r--compiler_and_linker/unsorted/CMachine.c13
-rw-r--r--compiler_and_linker/unsorted/CMangler.c719
-rw-r--r--compiler_and_linker/unsorted/CParser.c3520
-rw-r--r--compiler_and_linker/unsorted/CodeGen.c697
-rw-r--r--compiler_and_linker/unsorted/Operands.c1044
-rw-r--r--compiler_and_linker/unsorted/PCode.c299
-rw-r--r--compiler_and_linker/unsorted/PCodeInfo.c1308
-rw-r--r--compiler_and_linker/unsorted/PCodeUtilities.c348
-rw-r--r--compiler_and_linker/unsorted/RegisterInfo.c392
-rw-r--r--compiler_and_linker/unsorted/Registers.c225
-rw-r--r--compiler_and_linker/unsorted/StackFrame.c1265
-rw-r--r--compiler_and_linker/unsorted/TOC.c2041
24 files changed, 27122 insertions, 207 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CPrep.c b/compiler_and_linker/FrontEnd/C/CPrep.c
index e69bcfb..4e3ffea 100644
--- a/compiler_and_linker/FrontEnd/C/CPrep.c
+++ b/compiler_and_linker/FrontEnd/C/CPrep.c
@@ -1,7 +1,47 @@
#include "compiler.h"
#include "compiler/CError.h"
+#include "compiler/CInt64.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
#include "compiler/tokens.h"
#include "cos.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/CScope.h"
+#include "compiler/CodeGen.h"
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct PrepValue {
+ CInt64 val;
+ char is_unsigned;
+} PrepValue;
+
+typedef struct IfStack {
+ CPrepFileInfo *file;
+ SInt32 pos;
+ short state;
+} IfStack;
+
+enum {
+ IfState_0 = 0,
+ IfState_1 = 1,
+ IfState_2 = 2,
+ IfState_3 = 3,
+ IfState_4 = 4,
+ IfState_5 = 5
+};
+
+// forward declarations
+static PrepValue CPrep_ParseCond();
+static PrepValue CPrep_ParseBinary(PrepValue *rhs, short op);
+static char *XpandMacro(Macro *macro);
+static void prepmacro(Macro *macro);
+static void prepifskip();
+static void gotonexttoken();
extern SInt16 *CLT_filesp;
extern CPrepFileInfo **CLT_filestack;
@@ -9,11 +49,13 @@ extern CPrepFileInfo **CLT_filestack;
//#define OPT_OFFSET(optname) ((short) (((char *) (&copts.optname)) - ((char *) &copts)))
#define OPT_OFFSET(optname) ((short) ( &((COpts *)0)->optname ))
enum {
+ OPT_OFFSET_MASK = 0x1FFF,
OPT_FLAG_2000 = 0x2000,
- OPT_FLAG_4000 = 0x4000
+ OPT_FLAG_4000 = 0x4000,
+ OPT_FLAG_8000 = 0x8000
};
-struct {
+struct CompilerOption {
char *name;
short bits;
} compileroptions[138] = {
@@ -172,15 +214,15 @@ Macro **macrohashtable;
Boolean cprep_nomem_exit;
Boolean cprep_nostring;
Boolean cprep_eoltokens;
-static void *ifstack[100]; // TODO type+size
+static IfStack ifstack[64];
static short iflevel;
TokenStack tokenstack[128];
short tokenstacklevel;
-SInt32 cprep_cursymfile; // might be a ptr?
+CPrepFileInfo *cprep_cursymfile;
char *pos;
char *macropos;
char *nextcharpos;
-char CPrep_SkipNewCommentChar;
+unsigned char CPrep_SkipNewCommentChar;
Boolean preprocessing_only;
Handle stringmem;
SInt32 maxstringsize;
@@ -197,8 +239,12 @@ CPrepFileInfo *prep_file;
short filesp;
SInt32 linenumber;
static CPrepFileInfo *filestack[32];
-static void *cprep_files; // TODO type
-static SInt32 linetick;
+typedef struct CPrepFileInfoList {
+ struct CPrepFileInfoList *next;
+ CPrepFileInfo *fileinfo;
+} CPrepFileInfoList;
+static CPrepFileInfoList *cprep_files;
+static UInt32 linetick;
static Boolean waslockedmacro;
static Boolean include_once;
static time_t now_time;
@@ -206,7 +252,11 @@ static SInt32 lineoffset;
static Boolean was_prep_error;
static Boolean cprep_hasprepline;
static Boolean cprep_incondexpr;
-static void *cprep_packstack[100]; // TODO type+size
+struct PackStack {
+ HashNameNode *identifier;
+ short align_mode;
+};
+static struct PackStack cprep_packstack[128];
static short cprep_packstackp;
static Macro lineM;
static Macro fileM;
@@ -227,9 +277,15 @@ struct COptsPush {
struct COptsPush *next;
COpts opts;
};
+struct COptPush {
+ struct COptPush *next;
+ SInt32 id;
+ Boolean x8;
+ UInt8 value;
+};
static struct COptsPush *coptpushs;
-static void *coptpush; // TODO type
-static void *coptssave; // TODO type
+static struct COptPush *coptpush;
+static COpts *coptssave;
static Boolean dofreeaheap;
static GList mlist;
static Handle ts_buffer;
@@ -240,8 +296,10 @@ static SInt32 ts_elements;
SInt32 ts_preread_elements;
static SInt32 gDirectiveStart;
static SInt32 high_mem_mark;
-// static TStreamElement dummyelement; // in CPrep_CurStreamElement
static short exprtk;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
static void cannotopenerror(StringPtr filename, Boolean err) {
static char fname[64];
@@ -433,11 +491,15 @@ static Boolean setupfile(StringPtr filename, Boolean flag1, Boolean flag2) {
OSType file_type;
SInt32 file_size;
SInt32 file_dirid;
- CWMemHandle cache_hnd;
void *cache;
+ CWMemHandle cache_hnd;
SInt16 refnum;
SInt16 file_vrefnum;
char *extpos;
+ unsigned char *src;
+ char *append;
+ char *dst;
+ int len;
if (filesp >= 31) {
was_prep_error = 1;
@@ -446,10 +508,10 @@ static Boolean setupfile(StringPtr filename, Boolean flag1, Boolean flag2) {
}
memclrw(&prepinfo, sizeof(CPrepFileInfo));
- prepinfo.unkfield126 = !flag1; // may be wrong field!
+ prepinfo.unkfield126 = !flag1;
if (filename) {
memclrw(&fileinfo, sizeof(CWFileInfo));
- fileinfo.fullsearch = flag2;
+ fileinfo.fullsearch = flag1;
fileinfo.dependencyType = cwNormalDependency;
fileinfo.isdependentoffile = -1;
memcpy(myfilename, &filename[1], filename[0]);
@@ -458,7 +520,26 @@ static Boolean setupfile(StringPtr filename, Boolean flag1, Boolean flag2) {
if (CWFindAndLoadFile(cparamblkptr->context, myfilename, &fileinfo) != cwNoErr) {
if (filename[0] + strlen(".framework/Headers") < 255) {
if ((extpos = strchr(myfilename, '/'))) {
- // Do Me! 37D8C
+ src = filename + 1;
+ append = ".framework/Headers";
+ dst = myfilename;
+ len = filename[0];
+ while (dst < extpos) {
+ *(dst++) = *(src++);
+ len--;
+ }
+ while (*append) {
+ *(dst++) = *(append++);
+ }
+ while (len) {
+ *(dst++) = *(src++);
+ len--;
+ }
+ *dst = 0;
+ if (CWFindAndLoadFile(cparamblkptr->context, myfilename, &fileinfo) != cwNoErr) {
+ cannotopenerror(filename, 0);
+ return 0;
+ }
} else {
cannotopenerror(filename, 0);
return 0;
@@ -598,19 +679,519 @@ void CPrep_TokenStreamSetCurState(SInt32 *state) {
tk = lex();
}
-static void CPrep_StreamSkipToBrace() {}
-static void CPrep_StreamSkipBlock() {}
-void CPrep_StreamGetBlock() {}
-void CPrep_StreamGetSemicolon() {}
-void CPrep_StreamGetTemplate() {}
-void CPrep_StreamInsert() {}
-void CPrep_StreamRemove() {}
-void CPrep_RemoveTokens() {}
-void CPrep_TokenStreamFlush() {}
-static void CPrep_TokenSize() {}
-void CPrep_CurStreamElement() {}
+static SInt32 CPrep_StreamSkipToBrace(CPrepStreamFuncPtr func, SInt32 val) {
+ TStreamElement ts;
+ SInt32 v = val + 1;
+
+ do {
+ switch (lex()) {
+ case '{':
+ return v;
+ case 0:
+ case ';':
+ return 0;
+ case TK_IDENTIFIER:
+ if (func) {
+ ts = ts_current[-1];
+ func(&ts);
+ ts_current[-1] = ts;
+ tk = ts.tokentype;
+ }
+ break;
+ }
+ v++;
+ } while (1);
+}
+
+static SInt32 CPrep_StreamSkipBlock(CPrepStreamFuncPtr func, SInt32 val) {
+ TStreamElement ts;
+ SInt32 brace_level;
+ char save_asmpoundcomment;
+ char save_cplusplus;
+ char starttoken;
+ char endtoken;
+ SInt32 level;
+ SInt32 v;
+ SInt16 t;
+
+ save_asmpoundcomment = copts.asmpoundcomment;
+ save_cplusplus = copts.cplusplus;
+ level = 0;
+ brace_level = 1;
+ v = val + 1;
+
+loop:
+ v++;
+ switch ((t = lex())) {
+ case 0:
+ return 0;
+ case TK_ASM:
+ cprep_nostring = 1;
+ v++;
+ t = lex();
+ if ((t == TK_VOLATILE) || ((t == TK_IDENTIFIER) && !strcmp(tkidentifier->name, "__volatile__"))) {
+ v++;
+ t = lex();
+ }
+ if (!t)
+ return 0;
+ if (t == TK_NEG7) {
+ t = lex();
+ v++;
+ }
+ if (t == '(') {
+ starttoken = '(';
+ endtoken = ')';
+ } else if (t == '{') {
+ starttoken = '{';
+ endtoken = '}';
+ brace_level++;
+ }
+ level = 1;
+ in_assembler = 1;
+ v++;
+ t = lex();
+ if (t == '"') {
+ copts.cplusplus = 0;
+ copts.asmpoundcomment = 1;
+ goto loop;
+ }
+ if (t)
+ goto loop;
+ return 0;
+
+ case '(':
+ if (starttoken == t)
+ level++;
+ goto loop;
+ case ')':
+ if (level && endtoken == t && !--level) {
+ cprep_nostring = 0;
+ in_assembler = 0;
+ copts.cplusplus = save_cplusplus;
+ copts.asmpoundcomment = save_asmpoundcomment;
+ }
+ goto loop;
+
+ case TK_IDENTIFIER:
+ if (func) {
+ ts = ts_current[-1];
+ func(&ts);
+ ts_current[-1] = ts;
+ tk = ts.tokentype;
+ }
+ goto loop;
+
+ case '{':
+ brace_level++;
+ if (starttoken == t)
+ level++;
+ goto loop;
+ case '}':
+ if (level && endtoken == t && !--level) {
+ cprep_nostring = 0;
+ in_assembler = 0;
+ copts.cplusplus = save_cplusplus;
+ copts.asmpoundcomment = save_asmpoundcomment;
+ }
+ if (--brace_level > 0)
+ goto loop;
+ break;
+ default:
+ goto loop;
+ }
+
+ return v;
+}
+
+void CPrep_StreamGetBlock(TStream *stream, CPrepStreamFuncPtr func, int arg) {
+ Boolean save_eoltokens;
+ SInt32 start_offset;
+ Boolean tryflag;
+ SInt32 count;
+
+ start_offset = ts_current - ts_first - 1;
+ tryflag = 0;
+ stream->tokens = 0;
+ stream->firsttoken = NULL;
+ count = 0;
+ save_eoltokens = cprep_eoltokens;
+ cprep_eoltokens = 1;
+
+ switch (tk) {
+ case TK_TRY:
+ tryflag = 1;
+ case ':':
+ if (!(count = CPrep_StreamSkipToBrace(func, 0))) {
+ CError_Error(121);
+ cprep_eoltokens = save_eoltokens;
+ return;
+ }
+ case '{':
+ break;
+ default:
+ CError_Error(121);
+ cprep_eoltokens = save_eoltokens;
+ return;
+ }
+
+ if (!(count = CPrep_StreamSkipBlock(func, count))) {
+ CError_Error(121);
+ cprep_eoltokens = save_eoltokens;
+ return;
+ }
+
+ if (tryflag) {
+ tryloop:
+ switch (lex()) {
+ case TK_NEG7:
+ count++;
+ goto tryloop;
+ case TK_CATCH:
+ if (!(count = CPrep_StreamSkipToBrace(func, count)) || !(count = CPrep_StreamSkipBlock(func, count))) {
+ CError_Error(242);
+ cprep_eoltokens = save_eoltokens;
+ return;
+ }
+ if (lookahead_noeol() == TK_CATCH)
+ goto tryloop;
+ break;
+ default:
+ CError_Error(242);
+ cprep_eoltokens = save_eoltokens;
+ return;
+ }
+ }
+
+ cprep_eoltokens = save_eoltokens;
+ stream->tokens = count;
+ stream->firsttoken = galloc(count * sizeof(TStreamElement));
+ memcpy(stream->firsttoken, ts_first + start_offset, count * sizeof(TStreamElement));
+}
+
+void CPrep_StreamGetSemicolon(TStream *stream, CPrepStreamFuncPtr func) {
+ SInt32 count;
+ SInt32 start_offset;
+ Boolean save_eoltokens;
+
+ start_offset = ts_current - ts_first - 1;
+ save_eoltokens = cprep_eoltokens;
+ cprep_eoltokens = 1;
+ stream->tokens = 0;
+ stream->firsttoken = NULL;
+ count = 1;
+
+ while (tk && tk != ';') {
+ tk = lex();
+ if ((tk == TK_IDENTIFIER) && func) {
+ func(&ts_current[-1]);
+ tk = ts_current[-1].tokentype;
+ }
+ count++;
+ }
+
+ stream->tokens = count;
+ stream->firsttoken = galloc(count * sizeof(TStreamElement));
+ memcpy(stream->firsttoken, ts_first + start_offset, count * sizeof(TStreamElement));
+ cprep_eoltokens = save_eoltokens;
+}
+
+void CPrep_StreamGetTemplate(TStream *stream, CPrepStreamFuncPtr func) {
+ SInt32 count;
+ SInt32 start_offset;
+ Boolean save_eoltokens;
+ SInt16 level;
+
+ start_offset = ts_current - ts_first - 1;
+ save_eoltokens = cprep_eoltokens;
+ cprep_eoltokens = 1;
+ stream->tokens = 0;
+ stream->firsttoken = NULL;
+ count = 0;
+
+loop:
+ switch (tk) {
+ case 0:
+ CError_ErrorTerm(102);
+ case '}':
+ CError_Error(229);
+ return;
+ case ';':
+ count++;
+ break;
+ case TK_IDENTIFIER:
+ if (func) {
+ func(&ts_current[-1]);
+ tk = ts_current[-1].tokentype;
+ }
+ default:
+ count++;
+ tk = lex();
+ goto loop;
+ case '{':
+ level = 0;
+ do {
+ count++;
+ switch (tk) {
+ case TK_IDENTIFIER:
+ if (func) {
+ func(&ts_current[-1]);
+ tk = ts_current[-1].tokentype;
+ }
+ break;
+ case '{':
+ level++;
+ break;
+ case '}':
+ level--;
+ break;
+ }
+ if (level <= 0)
+ break;
+ if (!(tk = lex()))
+ CError_ErrorTerm(102);
+ } while (1);
+ if (lookahead() == ';') {
+ tk = lex();
+ count++;
+ }
+ }
+
+ stream->tokens = count;
+ stream->firsttoken = galloc(count * sizeof(TStreamElement));
+ memcpy(stream->firsttoken, ts_first + start_offset, count * sizeof(TStreamElement));
+ cprep_eoltokens = save_eoltokens;
+}
+
+void CPrep_StreamInsert(TStream *stream, SInt32 *state) {
+ if (ts_preread_elements + (ts_current - ts_first) + stream->tokens >= ts_elements)
+ CPrep_TSBufferGrow(stream->tokens);
+ if (ts_preread_elements)
+ memmove(ts_current + stream->tokens, ts_current, sizeof(TStreamElement) * ts_preread_elements);
+ memcpy(ts_current, stream->firsttoken, sizeof(TStreamElement) * stream->tokens);
+ ts_preread_elements += stream->tokens;
+ CPrep_TokenStreamGetState(state);
+}
+
+void CPrep_StreamRemove(TStream *stream, SInt32 *state) {
+ TStreamElement *end;
+ SInt32 amount;
+
+ end = ts_first + *state;
+ amount = ts_preread_elements + ((ts_current - ts_first) - *state - stream->tokens);
+ if (amount >= 0) {
+ if (amount)
+ memmove(end, end + stream->tokens, sizeof(TStreamElement) * amount);
+ ts_current = end;
+ ts_preread_elements = amount;
+ }
+}
+
+void CPrep_RemoveTokens(SInt32 amount) {
+#line 1296
+ CError_ASSERT(ts_preread_elements >= amount);
+
+ ts_preread_elements -= amount;
+ memmove(ts_current, ts_current + amount, sizeof(TStreamElement) * ts_preread_elements);
+}
+
+void CPrep_TokenStreamFlush() {
+ if (!ts_preread_elements)
+ ts_current = ts_first;
+}
+
+static int CPrep_TokenSize(char *str) {
+ int len;
+ int c;
+
+ if ((str[0] >= 'a' && str[0] <= 'z') || (str[0] >= 'A' && str[0] <= 'Z') || (str[0] == '_')) {
+ len = 1;
+ str++;
+ do {
+ c = *(str++);
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_'))
+ len++;
+ else
+ break;
+ } while (1);
+ return len;
+ }
+
+ switch (str[0]) {
+ case '*':
+ if (str[1] == '=') return 2;
+ break;
+ case '/':
+ if (str[1] == '=' || str[1] == '*' || str[1] == '/') return 2;
+ break;
+ case '%':
+ if (str[1] == '=') return 2;
+ break;
+ case '+':
+ if (str[1] == '=' || str[1] == '+') return 2;
+ break;
+ case '-':
+ if (str[1] == '>') return (str[2] == '*') ? 3 : 2;
+ if (str[1] == '=' || str[1] == '-') return 2;
+ break;
+ case '<':
+ if (str[1] == '=') return 2;
+ if (str[1] == '<') return (str[2] == '=') ? 3 : 2;
+ break;
+ case '>':
+ if (str[1] == '=') return 2;
+ if (str[1] == '>') return (str[2] == '=') ? 3 : 2;
+ break;
+ case '&':
+ if (str[1] == '=' || str[1] == '&') return 2;
+ break;
+ case '^':
+ if (str[1] == '=') return 2;
+ break;
+ case '|':
+ if (str[1] == '=' || str[1] == '|') return 2;
+ break;
+ case '=':
+ if (str[1] == '=') return 2;
+ break;
+ case '!':
+ if (str[1] == '=') return 2;
+ break;
+ case '.':
+ if (str[1] == '.' && str[2] == '.') return 3;
+ if (str[1] == '*') return 2;
+ break;
+ case ':':
+ if (str[1] == ':') return 2;
+ break;
+ }
+
+ return 1;
+}
+
+TStreamElement *CPrep_CurStreamElement() {
+ static TStreamElement dummyelement;
+ if (ts_first < ts_current)
+ return ts_current - 1;
+ else
+ return &dummyelement;
+}
+
+void CPrep_GetTokenContext(TStreamElement *token, CPrepFileInfo **tokenfile, SInt32 *selectionoffset, short *tokensize, SInt32 *plinenumber, char *buf1, short *tokenoffset, short *tokenlength, char *buf2, short *lastarg) {
+ // misassigned registers
+ SInt32 p;
+ TStreamElement *prevtoken;
+ char *filedata;
+ char *tokendata;
+ Boolean hasowndata;
+ SInt32 line;
+ SInt32 i;
+ char *r4;
+ int r5;
+ int r6;
+ char *r7;
+ char *r5x;
+ SInt16 c;
+
+ if (token && !token->tokenfile)
+ token = NULL;
+
+ prevtoken = token;
+ if (!token && ts_first < ts_current)
+ prevtoken = ts_current - 1;
+
+ if (prevtoken && !prevtoken->tokenfile) {
+#line 1454
+ CError_FATAL();
+ }
+
+ if (was_prep_error || !prevtoken) {
+ if (!prep_file)
+ CError_CannotOpen();
+ *tokenfile = prep_file;
+ if (!tokenstacklevel) {
+ p = pos - prep_file_start;
+ if (was_prep_error && p > 0)
+ p--;
+ } else {
+ p = tokenstack[0].pos - prep_file_start;
+ }
+ *selectionoffset = p;
+ } else {
+ *tokenfile = prevtoken->tokenfile;
+ p = prevtoken->tokenoffset;
+ *selectionoffset = p;
+ }
+
+ filedata = (*tokenfile)->textbuffer;
+ if (!filedata) {
+ filedata = getfiledata(&(*tokenfile)->textfile);
+ hasowndata = 1;
+ } else {
+ hasowndata = 0;
+ }
+
+ if (!cprep_hasprepline) {
+ line = 1;
+ for (i = 0; i < p; i++) {
+ if (filedata[i] == '\r')
+ line++;
+ }
+ *plinenumber = line;
+ } else {
+ *plinenumber = linenumber;
+ }
-void CPrep_GetTokenContext(TStreamElement *token, CPrepFileInfo **tokenfile, SInt32 *selectionoffset, short *tokensize, SInt32 *linenumber, char *buf1, short *tokenoffset, short *tokenlength, char *buf2, short *lastarg) {
+ tokendata = filedata + p;
+ *tokensize = CPrep_TokenSize(tokendata);
+ if (!token && tokenstacklevel == 1) {
+ r4 = macrostart;
+ r7 = macropos;
+ } else {
+ r4 = filedata;
+ r7 = tokendata;
+ }
+ *tokenoffset = 0;
+ r5 = 1;
+ while (r5 < 80 && (r7 - r5) >= r4 && r7[-r5] != '\r')
+ r5++;
+ r5--;
+ while ((c = r7[-r5]) && (c == ' ' || c == '\t' || c == 4))
+ r5--;
+ r6 = 0;
+ while ((c = r7[-r5]) != '\r' && c && r6 < 126) {
+ if (!r5)
+ *tokenoffset = r6;
+ if (c != 4) {
+ buf1[r6++] = (c != '\t') ? c : ' ';
+ }
+ r5--;
+ }
+ if (!r5) {
+ buf1[r6] = ' ';
+ *tokenoffset = r6;
+ buf1[r6 + 1] = 0;
+ *tokenlength = 1;
+ } else {
+ buf1[r6] = 0;
+ *tokenlength = CPrep_TokenSize(buf1 + *tokenoffset);
+ }
+
+ if (p > 16) {
+ r5x = tokendata - 16;
+ *lastarg = 16;
+ } else {
+ r5x = filedata;
+ *lastarg = p;
+ }
+ for (i = 0; i < 31 && *r5x; i++) {
+ buf2[i] = *(r5x++);
+ }
+ buf2[i] = 0;
+
+ if (hasowndata)
+ CWReleaseFileText(cparamblkptr->context, filedata);
+ was_prep_error = 0;
}
void CPrep_Error(short code) {
@@ -685,16 +1266,281 @@ void popfile() {
}
}
-static void prepoffset() {}
-static void prepoffset2() {}
-void CPrep_SetSourceFile() {}
-void CPrep_GetSourceFilePath() {}
-void CPrep_NewFileOffsetInfo() {}
-void CPrep_GetFileOffsetInfo() {}
-void CPrep_GetFileOffsetInfo2() {}
-void CPrep_ResetFileInfo() {}
-void CPrep_GetPrepPos() {}
-Boolean C_Compiler(CParams *param) {}
+static SInt32 prepoffset() {
+ if (filesp > 0)
+ return filestack[0]->pos;
+ else if (tokenstacklevel)
+ return tokenstack[0].pos - filestack[filesp]->textbuffer;
+ else
+ return pos - filestack[0]->textbuffer;
+}
+
+static SInt32 prepoffset2() {
+ return lineoffset;
+}
+
+void CPrep_SetSourceFile(FileOffsetInfo *foi) {
+ CPrepFileInfoList *list;
+
+ if (foi->file) {
+ if (foi->file == filestack[0]) {
+ if (cprep_cursymfile) {
+ if (cparamblkptr->isPrecompiling != 1)
+ ObjGen_SrcBreakName(NULL, 0, 0);
+ cprep_cursymfile = NULL;
+ }
+ } else {
+ if (cprep_cursymfile != foi->file) {
+ for (list = cprep_files; list; list = list->next) {
+ if (foi->file == list->fileinfo) {
+ if (cparamblkptr->isPrecompiling != 1)
+ ObjGen_SrcBreakName(list->fileinfo->nameNode, list->fileinfo->fileModDate, 0);
+ cprep_cursymfile = foi->file;
+ return;
+ }
+ }
+
+ list = galloc(sizeof(CPrepFileInfoList));
+ list->next = cprep_files;
+ cprep_files = list;
+ list->fileinfo = foi->file;
+ if (cparamblkptr->isPrecompiling != 1)
+ ObjGen_SrcBreakName(list->fileinfo->nameNode, list->fileinfo->fileModDate, 1);
+ cprep_cursymfile = foi->file;
+ }
+ }
+ }
+}
+
+HashNameNode *CPrep_GetSourceFilePath(CPrepFileInfo *fileinfo) {
+ HashNameNode *node;
+ if ((node = fileinfo->nameNode) == NULL)
+ node = CTool_GetPathName(&fileinfo->textfile, NULL);
+ return node;
+}
+
+void CPrep_NewFileOffsetInfo(FileOffsetInfo *foi, TStreamElement *ts) {
+ if (!ts || !ts->tokenfile) {
+ if (ts_first < ts_current) {
+ foi->file = ts_current[-1].tokenfile;
+ foi->tokenline = ts_current[-1].tokenline;
+ foi->tokenoffset = ts_current[-1].tokenoffset;
+ } else {
+ foi->file = filestack[filesp];
+ foi->tokenline = linenumber;
+ if (tokenstacklevel)
+ foi->tokenoffset = tokenstack[0].pos - filestack[filesp]->textbuffer;
+ else
+ foi->tokenoffset = pos - filestack[filesp]->textbuffer;
+ }
+ } else {
+ foi->file = ts->tokenfile;
+ foi->tokenline = ts->tokenline;
+ foi->tokenoffset = ts->tokenoffset;
+ }
+ foi->is_inline = 0;
+}
+
+SInt32 CPrep_GetFileOffsetInfo(FileOffsetInfo *foi) {
+ SInt32 p;
+ SInt32 i;
+
+ if (ts_first < ts_current && ts_current[-1].tokenfile == foi->file) {
+ if (ts_current[-1].tokenline > foi->tokenline)
+ foi->tokenline = ts_current[-1].tokenline;
+ if (ts_current[-1].tokenoffset > foi->tokenoffset)
+ foi->tokenoffset = ts_current[-1].tokenoffset;
+ } else if (foi->file == filestack[filesp]) {
+ if (linenumber > foi->tokenline)
+ foi->tokenline = linenumber;
+ if (tokenstacklevel)
+ p = tokenstack[0].pos - filestack[filesp]->textbuffer;
+ else
+ p = pos - filestack[filesp]->textbuffer;
+ if (p > foi->tokenoffset)
+ foi->tokenoffset = p;
+ } else {
+ for (i = filesp - 1; i >= 0; i--) {
+ if (foi->file == filestack[i]) {
+ if (filestack[i]->linenumber > foi->tokenline)
+ foi->tokenline = filestack[i]->linenumber;
+ if (filestack[i]->pos > foi->tokenoffset)
+ foi->tokenoffset = filestack[i]->pos;
+ break;
+ }
+ }
+ }
+
+ return foi->tokenline;
+}
+
+void CPrep_GetFileOffsetInfo2(FileOffsetInfo *foi, SInt32 *pLine, HashNameNode **pName) {
+ SInt32 p;
+ SInt32 i;
+
+ if (ts_first < ts_current && ts_current[-1].tokenfile == foi->file) {
+ if (ts_current[-1].tokenline > foi->tokenline)
+ foi->tokenline = ts_current[-1].tokenline;
+ if (ts_current[-1].tokenoffset > foi->tokenoffset)
+ foi->tokenoffset = ts_current[-1].tokenoffset;
+ } else if (foi->file == filestack[filesp]) {
+ if (linenumber > foi->tokenline)
+ foi->tokenline = linenumber;
+ if (tokenstacklevel)
+ p = tokenstack[0].pos - filestack[filesp]->textbuffer;
+ else
+ p = pos - filestack[filesp]->textbuffer;
+ if (p > foi->tokenoffset)
+ foi->tokenoffset = p;
+ } else {
+ for (i = filesp - 1; i >= 0; i--) {
+ if (foi->file == filestack[i]) {
+ if (filestack[i]->linenumber > foi->tokenline)
+ foi->tokenline = filestack[i]->linenumber;
+ if (filestack[i]->pos > foi->tokenoffset)
+ foi->tokenoffset = filestack[i]->pos;
+ break;
+ }
+ }
+ }
+
+ *pLine = foi->tokenline;
+#line 2010
+ CError_ASSERT(*pLine >= 0);
+ *pName = foi->file ? foi->file->nameNode : NULL;
+}
+
+void CPrep_ResetFileInfo(FileOffsetInfo *foi) {
+ // this function is empty so i can only assume...
+}
+
+void CPrep_GetPrepPos(CPrepFileInfo **file, SInt32 *ppos) {
+ *file = prep_file;
+ if (tokenstacklevel > 0)
+ *ppos = tokenstack->pos - prep_file_start;
+ else
+ *ppos = pos - prep_file_start;
+}
+
+UInt8 C_Compiler(CParams *param) {
+ TStreamElement ts;
+ UInt8 code;
+
+ CInt64_Init();
+ cprep_packstackp = 128;
+ widestring = 0;
+ cprep_nomem_exit = 0;
+ cparamblkptr = param;
+ prep_file = NULL;
+ lines = 0;
+ linenumber = 0;
+ cprep_hasprepline = 0;
+
+ if (CWDisplayLines(param->context, 0) != cwNoErr)
+ return 0;
+
+ linetick = COS_GetTicks() + 5;
+ code = 0;
+ copts.delete_exception = 1;
+ copts.som_call_opt = 1;
+ copts.template_patch = 1;
+ copts.template_friends = 1;
+ copts.simple_class_byval = 1;
+ copts.array_new_delete = 1;
+ copts.syspath_once = 1;
+ copts.arg_dep_lookup = 1;
+ copts.longlong = 1;
+ copts.longlong_prepeval = copts.longlong;
+ copts.vbase_ctor_offset = 1;
+ copts.vbase_abi_v2 = 1;
+ copts.optEH = 1;
+ copts.optEH2 = 0;
+ if (copts.cplusplus)
+ copts.const_strings = 1;
+ copts.inline_bottom_up = 1;
+
+ if (initheaps(&CError_NoMem)) {
+ releaseheaps();
+ cprep_nomem_exit = 1;
+ code = 255;
+ } else {
+ if (setjmp(errorreturn) == 0) {
+ InitNameHash();
+ setupprep();
+ CParser_Setup();
+ SetupPrecompiler(cparamblkptr->isPrecompiling);
+ SetupAssembler();
+ ObjGen_Setup();
+ PointerAnalysis_Setup();
+ CBrowse_Setup(param);
+
+ setupfile(NULL, 1, 0);
+ if (copts.oldprefixname[0])
+ setupfile(copts.oldprefixname, 1, 0);
+
+ coptssave = galloc(sizeof(COpts));
+ *coptssave = copts;
+ coptpushs = NULL;
+ coptpush = NULL;
+ preprocessing_only = param->isPreprocessing;
+ if (param->isPreprocessing)
+ CPrep_Preprocess();
+ else
+ cparser();
+
+ if (CWDisplayLines(param->context, lines) != cwNoErr)
+ anyerrors = 1;
+
+ if (tokenstacklevel) {
+ was_prep_error = 1;
+ CError_ErrorTerm(119);
+ } else if (iflevel) {
+ was_prep_error = 0;
+ ts.tokenfile = ifstack[iflevel - 1].file;
+ ts.tokenoffset = ifstack[iflevel - 1].pos;
+ if (iflevel)
+ CError_SetErrorToken(&ts);
+ CError_ErrorTerm(119);
+ }
+
+ if (!anyerrors) {
+ if (param->isPrecompiling == 1) {
+ CBrowse_Finish(param);
+ PrecompilerWrite();
+ } else if (!param->isPreprocessing) {
+ ObjGen_Finish();
+ CBrowse_Finish(param);
+ }
+ code = 1;
+ }
+
+ if (param->isPreprocessing) {
+ cparamblkptr->objectDataHandle = pplist.data;
+ pplist.data = NULL;
+ cparamblkptr->browseDataHandle = NULL;
+ }
+ } else {
+ CWDisplayLines(param->context, lines);
+ }
+
+ CParser_Cleanup();
+ CleanupPrecompiler();
+ CleanupAssembler();
+ ObjGen_Cleanup();
+ ObjGen_CodeCleanup();
+ PointerAnalysis_Cleanup();
+ cleanupprep();
+ CBrowse_Cleanup(param);
+ }
+
+ param->objectdata.compiledlines = lines;
+ if (cprep_nomem_exit) {
+ CompilerGetCString(7, string);
+ CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0);
+ }
+
+ return code;
+}
static void pushtokenseq(Macro *macro) {
if (tokenstacklevel >= 128) {
@@ -723,24 +1569,504 @@ void poptokenseq() {
spaceskip = 1;
}
-static void is_nextchar() {}
-static void ismacroname() {}
-static void ismacroname2() {}
-static void ismacroname5() {}
-static void ismacroname3() {}
-static void ismacroname4() {}
-void foundnl() {}
-void newline() {}
-static void gotonexttoken() {}
-short notendofline() {}
-static void CPrep_MacroRedefError() {}
-static void goendofline() {}
-static void CPrep_Define() {}
-static void prepundefine() {}
+static Boolean is_nextchar(short t) {
+ char *p = pos;
+ short level = tokenstacklevel;
+ int c;
+
+ do {
+ switch ((c = *p)) {
+ case 0:
+ if (level <= 0)
+ return 0;
+ p = tokenstack[--level].pos;
+ continue;
+ case '\r':
+ p++;
+ continue;
+ }
+ if (c == t)
+ return 1;
+ if (c != ' ' && (c < 9 || c > 12))
+ break;
+ p++;
+ } while (1);
+
+ return 0;
+}
+
+static Macro *ismacroname() {
+ Macro *scan;
+ Boolean save_macrocheck;
+ HashNameNode *name = tkidentifier;
+
+ for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) {
+ if (scan->name == name) {
+ if (scan->is_special) {
+ if (scan == &vecM && !copts.altivec_model)
+ return NULL;
+ if (scan == &stdcM && copts.cplusplus)
+ return NULL;
+ if (scan == &cpplM && !copts.cplusplus)
+ return NULL;
+ if (scan == &ecppM && (!copts.cplusplus || !copts.ecplusplus))
+ return NULL;
+ }
+
+ if (scan->xF) {
+ waslockedmacro = 1;
+ return NULL;
+ }
+
+ if (scan->xC) {
+ save_macrocheck = macrocheck;
+ macrocheck = 0;
+ gotonexttoken();
+ macrocheck = save_macrocheck;
+ if (*pos != '(')
+ return NULL;
+ }
+
+ return scan;
+ }
+ }
+
+ return NULL;
+}
+
+static Macro *ismacroname2(char *str) {
+ Macro *scan;
+ HashNameNode *name = tkidentifier;
+
+ for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) {
+ if (scan->name == name) {
+ if (scan->xF) {
+ waslockedmacro = 1;
+ return NULL;
+ }
+
+ if (scan->xC) {
+ while (*str == ' ' || (*str >= 9 && *str <= 12))
+ str++;
+ if (*str != '(' && !is_nextchar('('))
+ return NULL;
+ }
+
+ return scan;
+ }
+ }
+
+ return NULL;
+}
+
+static Macro *ismacroname5(char *str) {
+ Macro *scan;
+ HashNameNode *name = tkidentifier;
+
+ for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) {
+ if (scan->name == name) {
+ if (scan->xF) {
+ waslockedmacro = 1;
+ return NULL;
+ }
+
+ if (scan->xC) {
+ while (*str == ' ' || (*str >= 9 && *str <= 12))
+ str++;
+ if (*str != '(')
+ return NULL;
+ }
+
+ return scan;
+ }
+ }
+
+ return NULL;
+}
+
+static Macro *ismacroname3() {
+ Macro *scan;
+ HashNameNode *name = tkidentifier;
+
+ for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) {
+ if (scan->name == name) {
+ if (scan->is_special) {
+ if (scan == &vecM && !copts.altivec_model)
+ return NULL;
+ if (scan == &stdcM && copts.cplusplus)
+ return NULL;
+ if (scan == &cpplM && !copts.cplusplus)
+ return NULL;
+ }
+ break;
+ }
+ }
+
+ return scan;
+}
+
+static Macro *ismacroname4(HashNameNode *name) {
+ Macro *scan;
+
+ for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) {
+ if (scan->name == name) {
+ if (scan->is_special) {
+ if (scan == &vecM && !copts.altivec_model)
+ return NULL;
+ if (scan == &stdcM && copts.cplusplus)
+ return NULL;
+ if (scan == &cpplM && !copts.cplusplus)
+ return NULL;
+ }
+ break;
+ }
+ }
+
+ return scan;
+}
+
+void foundnl() {
+ if (!tokenstacklevel) {
+ if (preprocessing_only)
+ CPrep_PreprocessDumpNewLine();
+ linenumber++;
+ lines++;
+ if (filesp <= 0)
+ lineoffset = pos - filestack[0]->textbuffer;
+ }
+}
+
+void newline() {
+ foundnl();
+ nlflag = 1;
+ at_linestart = 1;
+ spaceskip = 1;
+ if (COS_GetTicks() > linetick) {
+ if (CWDisplayLines(cparamblkptr->context, lines) != cwNoErr)
+ CError_UserBreak();
+ linetick = COS_GetTicks() + 5;
+ }
+}
+
+static void gotonexttoken() {
+ char *save_pos;
+ Macro *macro;
+ char c;
+
+loop:
+ switch ((c = prepskipnextchar())) {
+ case 0:
+ if (tokenstacklevel) {
+ poptokenseq();
+ goto loop;
+ }
+ if (tokenstacklevel > 0 || pos >= prep_file_end) {
+ if (filesp > 0) {
+ popfile();
+ goto loop;
+ }
+ return;
+ }
+ pos = nextcharpos;
+ goto loop;
+ case '\r':
+ newline();
+ pos = nextcharpos;
+ goto loop;
+ }
+
+ if (macrocheck && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_'))) {
+ pos = ReadIdentifier(save_pos = pos);
+ if ((macro = ismacroname())) {
+ prepmacro(macro);
+ goto loop;
+ } else {
+ pos = save_pos;
+ }
+ }
+}
+
+short notendofline() {
+ char *save_pos;
+ Macro *macro;
+ char c;
+
+loop:
+ switch ((c = prepskipnextchar())) {
+ case 0:
+ if (tokenstacklevel) {
+ poptokenseq();
+ goto loop;
+ }
+ case '\r':
+ return 0;
+ }
+
+ if (macrocheck && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_'))) {
+ pos = ReadIdentifier(save_pos = pos);
+ if ((macro = ismacroname())) {
+ prepmacro(macro);
+ goto loop;
+ } else {
+ pos = save_pos;
+ }
+ }
+
+ return 1;
+}
+
+static void CPrep_MacroRedefError(char *name, Boolean *flag) {
+ if (!*flag) {
+ if (copts.gcc_extensions) {
+ CPrep_WarningName(108, name);
+ } else if (copts.cpp_extensions) {
+ if (copts.pedantic)
+ CPrep_WarningName(108, name);
+ } else {
+ CPrep_ErrorName(108, name);
+ }
+ *flag = 1;
+ }
+}
+
+static void goendofline() {
+ if (notendofline()) {
+ CPrep_Error(113);
+ skipendofline();
+ }
+}
+
+static void CPrep_Define() {
+ Macro *existing_macro; // r31
+ HashNameNode *name; // r29
+ short r28; // r28
+ Boolean r27; // r27
+ Macro *macro; // r20
+ short t; // r17
+ Boolean error_flag;
+
+ macrocheck = 0;
+ nlflag = 0;
+ t = lexidentifier();
+ if (nlflag) {
+ CPrep_Error(112);
+ skipendofline();
+ }
+ if (t != TK_IDENTIFIER) {
+ CPrep_Error(107);
+ skipendofline();
+ return;
+ }
+
+ macro = ismacroname3();
+ name = tkidentifier;
+ error_flag = 0;
+ r27 = 0;
+ if (prepcurchar() == '(') {
+ r28 = 1;
+ pos = nextcharpos;
+ // fix me
+ } else {
+ macro = galloc(sizeof(Macro));
+ r28 = 0;
+ }
+
+ if (existing_macro && (existing_macro->xC & 0x7FFF) != r28)
+ CPrep_MacroRedefError(name->name, &error_flag);
+
+ macro->name = name;
+ macro->xC = r27 ? (r28 | 0x8000) : r28;
+ macro->is_special = 0;
+ macro->xF = 0;
+
+ if (r28 > 1) {
+ // fix me
+ }
+
+ mlist.size = 0;
+ if (notendofline()) {
+ // fix me
+ } else {
+ // fix me
+ }
+}
+
+static void prepundefine() {
+ short t;
+ Macro *macro;
+ Macro **scan;
+ HashNameNode *name;
+
+ nlflag = 0;
+ t = lexidentifier();
+ if (nlflag) {
+ CPrep_Error(112);
+ skipendofline();
+ } else if (t != TK_IDENTIFIER) {
+ CPrep_Error(107);
+ skipendofline();
+ } else {
+ name = tkidentifier;
+ for (scan = &macrohashtable[name->hashval], macro = *scan; macro; scan = &macro->next, macro = *scan) {
+ if (macro->name == name) {
+ *scan = macro->next;
+ macrocheck = 1;
+ return;
+ }
+ }
+ goendofline();
+ }
+}
+
static Boolean CPrep_CheckTarget() {}
static Boolean CPrep_CheckOption() {}
-static void CPrep_XpandDefinedCheck() {}
-static void XpandString() {}
+static char *CPrep_XpandDefinedCheck(char *) {}
+
+static char *XpandString(Macro *macro, char *somepos) {
+ // almost matches, r22 and r23 are swapped at the end
+ short start_level;
+ char *curpos;
+ char *tmp;
+ SInt32 tmplen;
+ SInt32 i;
+ char *macro_output;
+ Macro *macro2;
+ int c;
+ char *resultptr;
+
+ pushtokenseq(macro);
+ macropos = somepos;
+ macrostart = somepos;
+ start_level = tokenstacklevel;
+ pos = somepos;
+ mlist.size = 0;
+
+ while (tokenstacklevel >= start_level) {
+ loop:
+ switch (*(curpos = pos)) {
+ case 4:
+ AppendGListByte(&mlist, 4);
+ pos = ReadIdentifier(somepos = ++pos);
+ if (cprep_incondexpr && !strcmp(tkidentifier->name, "defined") && (tmp = CPrep_XpandDefinedCheck(pos)))
+ pos = tmp;
+ AppendGListData(&mlist, somepos, pos - somepos);
+ goto loop;
+ case '"':
+ case '\'':
+ somepos = pos++;
+ CPrep_MatchChar(*somepos, 0);
+ AppendGListData(&mlist, somepos, pos - somepos);
+ goto loop;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I':
+ case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i':
+ case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+ case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ case '_':
+ pos = ReadIdentifier(curpos);
+ waslockedmacro = 0;
+ if (cprep_incondexpr && !strcmp(tkidentifier->name, "defined") && (tmp = CPrep_XpandDefinedCheck(pos))) {
+ pos = tmp;
+ AppendGListData(&mlist, curpos, pos - curpos);
+ goto loop;
+ } else {
+ if (macro)
+ macro2 = ismacroname2(pos);
+ else
+ macro2 = ismacroname5(pos);
+ if (macro2) {
+ AppendGListByte(&mlist, 5);
+ tmplen = mlist.size;
+ if (tmplen > 0x20000) {
+ macropos = pos;
+ CPrep_Error(111);
+ return "";
+ }
+ curpos = aalloc(tmplen);
+ memcpy(curpos, *mlist.data, tmplen);
+ macro_output = XpandMacro(macro2);
+ if (tokenstacklevel == start_level) {
+ for (i = strlen(macro_output) - 1; i > 0; i--) {
+ switch (macro_output[i]) {
+ case ' ':
+ case '"':
+ case '\'':
+ case ';':
+ goto exit_innermost_loop;
+ }
+ }
+ exit_innermost_loop:
+ if (i > 0) {
+ mlist.size = 0;
+ AppendGListName(&mlist, &macro_output[i + 1]);
+ AppendGListID(&mlist, pos);
+ pos = aalloc(mlist.size);
+ memcpy(pos, *mlist.data, mlist.size);
+ mlist.size = 0;
+ AppendGListData(&mlist, curpos, tmplen);
+ AppendGListData(&mlist, macro_output, i + 1);
+ } else {
+ mlist.size = 0;
+ AppendGListName(&mlist, macro_output);
+ AppendGListID(&mlist, pos);
+ macro_output = aalloc(mlist.size);
+ memcpy(macro_output, *mlist.data, mlist.size);
+ mlist.size = 0;
+ pos = macro_output;
+ AppendGListData(&mlist, curpos, tmplen);
+ }
+ } else {
+ mlist.size = 0;
+ AppendGListData(&mlist, curpos, tmplen);
+ AppendGListID(&mlist, macro_output);
+ if (tokenstacklevel < start_level)
+ goto skip_null_term;
+ mlist.size--;
+ goto loop;
+ }
+ } else {
+ if (waslockedmacro)
+ AppendGListByte(&mlist, 4);
+ AppendGListData(&mlist, curpos, pos - curpos);
+ goto loop;
+ }
+ }
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ AppendGListByte(&mlist, *(pos++));
+ do {
+ c = *pos;
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || (c >= '0' && c <= '9')) {
+ AppendGListByte(&mlist, c);
+ pos++;
+ } else {
+ break;
+ }
+ } while (1);
+ goto loop;
+ default:
+ AppendGListByte(&mlist, *(pos++));
+ goto loop;
+ case 0:
+ if (tokenstacklevel >= start_level)
+ poptokenseq();
+ }
+ }
+
+ AppendGListByte(&mlist, 0);
+skip_null_term:
+ if ((tmplen = mlist.size) > 0x20000) {
+ CPrep_Error(111);
+ return "";
+ } else {
+ resultptr = aalloc(tmplen);
+ memcpy(resultptr, *mlist.data, tmplen);
+ return resultptr;
+ }
+}
+
char *CPrep_GetFileName(char *buffer, Boolean flag1, Boolean flag2) {
}
@@ -795,22 +2121,364 @@ static char *XpandSpecialMacro(Macro *macro) {
}
}
-static void XpandMacro() {}
-static void prepmacro() {}
-void macrotest() {}
-void CPrep_PragmaLex() {}
-void CPrep_PushOption() {}
-void CPrep_PopOption() {}
-static void CPrep_PragmaImExport() {}
-static void pragma_on_off_reset() {}
-static void CPrep_PragmaOnceName() {}
-static void pragma_precompile_target() {}
-static void CPrep_DefinePragmaOnceMacro() {}
-static void CPrep_PragmaOnce() {}
-static void CPrep_PragmaUnused() {}
-static void CPrep_PragmaInlineDepth() {}
-static void CPrep_PragmaInlineMaxSize() {}
-static void CPrep_PragmaInlineMaxTotalSize() {}
+static char *XpandMacro(Macro *macro) {
+}
+
+static void prepmacro(Macro *macro) {
+ Boolean save_spaceskip;
+ char *result;
+
+ macrocheck = 0;
+ dofreeaheap = 0;
+ save_spaceskip = spaceskip;
+ result = XpandMacro(macro);
+ macrocheck = 1;
+ pushtokenseq(NULL);
+ macropos = result;
+ pos = result;
+ macrostart = result;
+ dofreeaheap = 1;
+ macrocheck = 0;
+ spaceskip = save_spaceskip;
+}
+
+Boolean macrotest() {
+ Macro *macro;
+ if ((macro = ismacroname())) {
+ prepmacro(macro);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+short CPrep_PragmaLex(Boolean no_err) {
+ if (notendofline())
+ return plex();
+ if (!no_err)
+ CPrep_Error(113);
+ return 0;
+}
+
+void CPrep_PushOption(SInt32 id, char value) {
+ struct COptPush *opt;
+ struct COptPush *newopt;
+
+ opt = coptpush;
+ do {
+ if (!opt || (opt->x8 && opt->id == id)) {
+ newopt = galloc(sizeof(struct COptPush));
+ newopt->next = coptpush;
+ coptpush = opt = newopt;
+ break;
+ }
+ if (!opt->x8)
+ break;
+ opt = opt->next;
+ } while (1);
+
+ opt->value = ((UInt8 *) &copts)[id];
+ opt->id = id;
+ opt->x8 = 1;
+ ((UInt8 *) &copts)[id] = value;
+}
+
+void CPrep_PopOption(SInt32 id) {
+ struct COptPush *opt;
+
+ for (opt = coptpush; opt; opt = opt->next) {
+ if (opt->x8 && opt->id == id) {
+ ((UInt8 *) &copts)[id] = opt->value;
+ opt->x8 = 0;
+ return;
+ }
+ }
+
+ ((UInt8 *) &copts)[id] = ((UInt8 *) coptssave)[id];
+}
+
+static void CPrep_PragmaImExport(int flags) {
+ // does not match - weirdness with the branching inside the loop
+ NameSpaceObjectList *list;
+
+ do {
+ if (!notendofline())
+ break;
+ if (plex() != TK_IDENTIFIER)
+ break;
+
+ if (!(list = CScope_GetLocalObject(cscope_root, tkidentifier))) {
+ break;
+ } else {
+ while (list) {
+ if (list->object->otype == OT_OBJECT) {
+ switch (OBJECT(list->object)->datatype) {
+ case DDATA:
+ case DFUNC:
+ OBJECT(list->object)->flags |= flags;
+ break;
+ default:
+ CPrep_Warning(186);
+ return;
+ }
+ }
+ list = list->next;
+ }
+ }
+
+ if (!notendofline())
+ return;
+ } while (plex() == ',' && notendofline());
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+}
+
+static void pragma_on_off_reset(UInt32 bits) {
+ Boolean flag = (bits & OPT_FLAG_2000) != 0;
+ int imex_flags;
+
+ if (notendofline() && plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "on")) {
+ CPrep_PushOption(bits & OPT_OFFSET_MASK, 1);
+ return;
+ }
+ if (!strcmp(tkidentifier->name, "off")) {
+ CPrep_PushOption(bits & OPT_OFFSET_MASK, 0);
+ return;
+ }
+ if (!strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(bits & OPT_OFFSET_MASK);
+ return;
+ }
+ if (flag && !strcmp(tkidentifier->name, "list")) {
+ if (cparamblkptr->isPreprocessing) {
+ skipendofline();
+ return;
+ }
+
+ macrocheck = 1;
+ if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(internal))
+ imex_flags = OBJECT_FLAGS_10;
+ else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(import))
+ imex_flags = OBJECT_FLAGS_20;
+ else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(export))
+ imex_flags = OBJECT_FLAGS_40;
+ else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(lib_export))
+ imex_flags = OBJECT_FLAGS_60;
+ else
+#line 3610
+ CError_FATAL();
+ CPrep_PragmaImExport(imex_flags);
+ return;
+ }
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+}
+
+static HashNameNode *CPrep_PragmaOnceName(StringPtr name, Boolean flag) {
+ // does not match, can't be bothered to fix it atm
+ short len;
+ char myname[256];
+ unsigned char *src;
+ char *dst;
+
+ len = name[0];
+ if (len > 250)
+ len = 250;
+
+ dst = &myname[1];
+ src = &name[1];
+ while (len-- > 0) {
+ *(dst++) = tolower(*(src++));
+ }
+ *dst = 0;
+
+ myname[0] = (copts.syspath_once && flag) ? '$' : -'\\';
+ return GetHashNameNodeExport(myname);
+}
+
+static void pragma_precompile_target() {
+ if (!notendofline()) {
+ CPrep_Error(112);
+ return;
+ }
+
+ if (plex() != TK_STRING) {
+ CPrep_Error(117);
+ skipendofline();
+ return;
+ }
+
+ if (ispascalstring) {
+ CPrep_Error(101);
+ skipendofline();
+ return;
+ }
+
+ precomp_target_str = tkstring;
+ goendofline();
+}
+
+static void CPrep_DefinePragmaOnceMacro(StringPtr name, Boolean flag) {
+ HashNameNode *namenode;
+ Macro *macro;
+
+ namenode = CPrep_PragmaOnceName(name, flag);
+ if (!ismacroname4(namenode)) {
+ macro = galloc(sizeof(Macro));
+ memclrw(macro, sizeof(Macro));
+ macro->name = namenode;
+ macro->next = macrohashtable[namenode->hashval];
+ macrohashtable[namenode->hashval] = macro;
+ }
+}
+
+static void CPrep_PragmaOnce() {
+ if (notendofline()) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "on")) {
+ include_once = 1;
+ return;
+ } else if (!strcmp(tkidentifier->name, "off")) {
+ include_once = 0;
+ return;
+ }
+ }
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ } else {
+ Str255 filename;
+ COS_FileGetFSSpecInfo(&prep_file->textfile, NULL, NULL, filename);
+ CPrep_DefinePragmaOnceMacro(filename, prep_file->unkfield126);
+ }
+}
+
+static void CPrep_PragmaUnused() {
+ NameSpace *nspace;
+ NameSpaceObjectList *list;
+ short t;
+
+ if (cparamblkptr->isPreprocessing) {
+ skipendofline();
+ return;
+ }
+
+ if (cscope_currentfunc && notendofline() && plex() == '(' && notendofline()) {
+ restart:
+ if (plex() == TK_IDENTIFIER) {
+ for (nspace = cscope_current; nspace; nspace = nspace->parent) {
+ if (nspace->is_global)
+ break;
+
+ list = CScope_GetLocalObject(nspace, tkidentifier);
+ if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DLOCAL) {
+ OBJECT(list->object)->flags |= OBJECT_FLAGS_UNUSED;
+ if (notendofline()) {
+ t = plex();
+ if (t == ')')
+ return;
+ if (t == ',' && notendofline())
+ goto restart;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+}
+
+static void CPrep_PragmaInlineDepth() {
+ int lv;
+
+ if (notendofline() && plex() == '(' && notendofline()) {
+ switch (plex()) {
+ case TK_IDENTIFIER:
+ if (strcmp(tkidentifier->name, "smart"))
+ CPrep_Warning(186);
+ else
+ copts.inlinelevel = 0;
+ break;
+ case TK_INTCONST:
+ lv = CInt64_GetULong(&tkintconst);
+ if (lv >= 0 && lv <= 1024)
+ copts.inlinelevel = lv ? lv : -1;
+ else
+ CPrep_Warning(186);
+ break;
+ default:
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+
+ if (!notendofline() || plex() != ')') {
+ CPrep_Warning(115);
+ }
+ if (notendofline()) {
+ CPrep_Warning(113);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ }
+}
+
+static void CPrep_PragmaInlineMaxSize() {
+ if (notendofline() && plex() == '(' && notendofline()) {
+ switch (plex()) {
+ case TK_INTCONST:
+ copts.inline_max_size = CInt64_GetULong(&tkintconst);
+ break;
+ default:
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+
+ if (!notendofline() || plex() != ')') {
+ CPrep_Warning(115);
+ }
+ if (notendofline()) {
+ CPrep_Warning(113);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ }
+}
+
+static void CPrep_PragmaInlineMaxTotalSize() {
+ if (notendofline() && plex() == '(' && notendofline()) {
+ switch (plex()) {
+ case TK_INTCONST:
+ copts.inline_max_total_size = CInt64_GetULong(&tkintconst);
+ break;
+ default:
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+
+ if (!notendofline() || plex() != ')') {
+ CPrep_Warning(115);
+ }
+ if (notendofline()) {
+ CPrep_Warning(113);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ }
+}
static void pragma_segment() {
short i;
@@ -841,7 +2509,40 @@ static void pragma_segment() {
}
}
-static void pragma_options() {}
+static void pragma_options() {
+ if (notendofline() && plex() == TK_IDENTIFIER && !strcmp(tkidentifier->name, "align") && notendofline() && plex() == '=' && notendofline() && plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(align_mode));
+ goto done;
+ } else if (!strcmp(tkidentifier->name, "native")) {
+ CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode2_PPC);
+ goto done;
+ } else if (!strcmp(tkidentifier->name, "mac68k")) {
+ CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode0_Mac68k);
+ goto done;
+ } else if (!strcmp(tkidentifier->name, "mac68k4byte")) {
+ CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode1_Mac68k4byte);
+ goto done;
+ } else if (!strcmp(tkidentifier->name, "power")) {
+ CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode2_PPC);
+ goto done;
+ } else if (!strcmp(tkidentifier->name, "packed")) {
+ CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode8_Packed);
+ goto done;
+ }
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+
+done:
+ if (notendofline()) {
+ CPrep_Error(113);
+ skipendofline();
+ }
+}
static void pragma_push() {
struct COptsPush *push;
@@ -863,35 +2564,1120 @@ static void pragma_pop() {
}
}
-static void pragma_overload() {}
-static void pragma_optimization_level() {}
-static void pragma_opt_unroll_count() {}
-static void pragma_opt_unroll_instr_count() {}
-static void pragma_pack() {}
-static void pragma_comment() {}
-static void pragma_message() {}
-static void preppragma() {}
-static void prepinclude() {}
-static void prepline() {}
-static void CPrep_GetPrepType() {}
-static void CPrep_ParseUnary() {}
-static void CPrep_ParseBinary() {}
-static void CPrep_ParseCond() {}
-static void doevalconstexpr() {}
-static void pushifstate() {}
-static void popifstate() {}
-static void positiveif() {}
-static void negativeif() {}
-static void prepif() {}
-static void prepifdef() {}
-static void prepifndef() {}
-static void prepelif() {}
-static void prepelse() {}
-static void prependif() {}
-static void prepifskip() {}
-void preprocessor() {}
-void CPrep_BrowserTokenOffset() {}
-void CPrep_BrowserFileOffset() {}
+static void pragma_overload() {
+ Object *obj;
+
+ if (cparamblkptr->isPreprocessing) {
+ skipendofline();
+ return;
+ }
+
+ nlflag = 0;
+ tk = lex();
+ if ((obj = CParser_ParseObject())) {
+ if (obj->sclass && obj->sclass != 0x103)
+ CPrep_Error(177);
+ obj->qual |= Q_OVERLOAD;
+ } else {
+ CPrep_Error(186);
+ }
+
+ if (nlflag)
+ CPrep_Error(112);
+ if (tk != ';')
+ CPrep_Error(123);
+}
+
+static void pragma_optimization_level() {
+ short t;
+ int lv;
+
+ if (notendofline()) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ lv = CInt64_GetULong(&tkintconst);
+ if (lv >= 0 && lv <= 4) {
+ if (copts.crippled && lv > 1) {
+ CPrep_Warning(385);
+ lv = 1;
+ }
+ CPrep_PushOption(OPT_OFFSET(optimizationlevel), lv);
+ CodeGen_UpdateOptimizerOptions();
+ CodeGen_UpdateBackEndOptions();
+ } else {
+ CPrep_Error(154);
+ skipendofline();
+ }
+ } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(optimizationlevel));
+ CodeGen_UpdateOptimizerOptions();
+ CodeGen_UpdateBackEndOptions();
+ } else {
+ CPrep_Error(105);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+}
+
+static void pragma_opt_unroll_count() {
+ short t;
+ int lv;
+
+ if (notendofline()) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ lv = CInt64_GetULong(&tkintconst);
+ if (lv >= 0 && lv <= 127) {
+ CPrep_PushOption(OPT_OFFSET(loop_unroll_count), lv);
+ CodeGen_UpdateOptimizerOptions();
+ CodeGen_UpdateBackEndOptions();
+ } else {
+ CPrep_Error(154);
+ skipendofline();
+ }
+ } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(loop_unroll_count));
+ CodeGen_UpdateOptimizerOptions();
+ CodeGen_UpdateBackEndOptions();
+ } else {
+ CPrep_Error(105);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+}
+
+static void pragma_opt_unroll_instr_count() {
+ short t;
+ int lv;
+
+ if (notendofline()) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ lv = CInt64_GetULong(&tkintconst);
+ if (lv >= 0 && lv <= 127) {
+ CPrep_PushOption(OPT_OFFSET(loop_unroll_size_threshold), lv);
+ CodeGen_UpdateOptimizerOptions();
+ CodeGen_UpdateBackEndOptions();
+ } else {
+ CPrep_Error(154);
+ skipendofline();
+ }
+ } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(loop_unroll_size_threshold));
+ CodeGen_UpdateOptimizerOptions();
+ CodeGen_UpdateBackEndOptions();
+ } else {
+ CPrep_Error(105);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+}
+
+static void pragma_pack() {
+ int t;
+ int i;
+ Boolean did_push;
+ Boolean did_pop;
+
+ if (notendofline() && plex() == '(') {
+ macrocheck = 1;
+ if (notendofline() && ((t = plex()) == ')')) {
+ copts.align_mode = coptssave->align_mode;
+ } else {
+ did_push = did_pop = 0;
+ do {
+ if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "push")) {
+ if (cprep_packstackp) {
+ cprep_packstackp--;
+ cprep_packstack[cprep_packstackp].identifier = NULL;
+ cprep_packstack[cprep_packstackp].align_mode = copts.align_mode;
+ did_push = 1;
+ } else {
+ CPrep_Warning(186);
+ }
+ } else if (!strcmp(tkidentifier->name, "pop")) {
+ if (cprep_packstackp < 128) {
+ copts.align_mode = cprep_packstack[cprep_packstackp].align_mode;
+ cprep_packstackp++;
+ did_pop = 1;
+ } else {
+ CPrep_Warning(186);
+ }
+ } else {
+ if (did_push) {
+ cprep_packstack[cprep_packstackp].identifier = tkidentifier;
+ } else if (did_pop) {
+ for (i = cprep_packstackp - 1; i < 128; i++) {
+ if (cprep_packstack[i].identifier == tkidentifier)
+ break;
+ }
+ if (i < 128) {
+ copts.align_mode = cprep_packstack[i].align_mode;
+ cprep_packstackp = i + 1;
+ } else {
+ CPrep_Warning(186);
+ }
+ } else {
+ CPrep_Warning(186);
+ }
+ did_pop = 0;
+ did_push = 0;
+ }
+ } else {
+ if (t == TK_INTCONST) {
+ switch (CInt64_GetULong(&tkintconst)) {
+ case 0:
+ copts.align_mode = coptssave->align_mode;
+ break;
+ case 1:
+ copts.align_mode = AlignMode3_1Byte;
+ break;
+ case 2:
+ copts.align_mode = AlignMode4_2Byte;
+ break;
+ case 4:
+ copts.align_mode = AlignMode5_4Byte;
+ break;
+ case 8:
+ copts.align_mode = AlignMode6_8Byte;
+ break;
+ case 16:
+ copts.align_mode = AlignMode7_16Byte;
+ break;
+ default:
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ }
+ }
+ did_pop = 0;
+ did_push = 0;
+ }
+
+ if (notendofline())
+ t = plex();
+ if (t != ',')
+ break;
+ t = plex();
+ } while (1);
+ }
+ if (t != ')' && copts.warn_illpragma)
+ CPrep_Warning(186);
+ macrocheck = 0;
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ }
+}
+
+static void pragma_comment() {
+ int t;
+ short start_tokenstacklevel = tokenstacklevel;
+
+ if (notendofline() && plex() == '(') {
+ if (notendofline()) {
+ t = plex();
+ if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "compiler")) {
+ t = plex();
+ } else if (!strcmp(tkidentifier->name, "exestr") || !strcmp(tkidentifier->name, "linker") || !strcmp(tkidentifier->name, "user")) {
+ if (plex() == ',') {
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ if (t == TK_STRING) {
+ while (t == TK_STRING) {
+ macrocheck = 1;
+ if (tokenstacklevel == start_tokenstacklevel && !notendofline())
+ break;
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+ } else if (!strcmp(tkidentifier->name, "lib")) {
+ if (plex() == ',') {
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ if (t == TK_STRING) {
+ while (t == TK_STRING) {
+ macrocheck = 1;
+ if (tokenstacklevel == start_tokenstacklevel && !notendofline())
+ break;
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ return;
+ }
+ }
+
+ if (t != ')') {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+}
+
+static void pragma_message() {
+ int t;
+ short start_tokenstacklevel;
+ char str[128];
+ char *ptr;
+
+ if (notendofline() && plex() == '(') {
+ if (notendofline()) {
+ start_tokenstacklevel = tokenstacklevel;
+ ptr = str;
+ str[0] = 0;
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ if (t == TK_STRING) {
+ while (t == TK_STRING) {
+ strncpy(ptr, tkstring, sizeof(str) - (ptr - str));
+ str[sizeof(str) - 1] = 0;
+ ptr = str + strlen(str);
+
+ macrocheck = 1;
+ if (tokenstacklevel == start_tokenstacklevel && !notendofline())
+ break;
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ }
+
+ CWReportMessage(cparamblkptr->context, NULL, str, NULL, messagetypeInfo, 337);
+ skipendofline();
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+ } else if (plex() != ')') {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ }
+}
+
+static void preppragma() {
+ struct CompilerOption *opt;
+ Boolean save_eoltokens;
+
+ if (notendofline()) {
+ macrocheck = 0;
+ if (lexidentifier() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "pack")) {
+ pragma_pack();
+ } else if (!strcmp(tkidentifier->name, "optimization_level")) {
+ pragma_optimization_level();
+ } else if (!strcmp(tkidentifier->name, "once")) {
+ CPrep_PragmaOnce();
+ } else if (!strcmp(tkidentifier->name, "unused")) {
+ CPrep_PragmaUnused();
+ } else if (!strcmp(tkidentifier->name, "inline_depth")) {
+ CPrep_PragmaInlineDepth();
+ } else if (!strcmp(tkidentifier->name, "inline_max_size")) {
+ CPrep_PragmaInlineMaxSize();
+ } else if (!strcmp(tkidentifier->name, "inline_max_total_size")) {
+ CPrep_PragmaInlineMaxTotalSize();
+ } else if (!strcmp(tkidentifier->name, "opt_pointer_analysis_mode")) {
+ PointerAnalysis_PragmaMode();
+ } else if (!strcmp(tkidentifier->name, "options")) {
+ pragma_options();
+ macrocheck = 1;
+ return;
+ } else if (!strcmp(tkidentifier->name, "segment")) {
+ pragma_segment();
+ } else if (!strcmp(tkidentifier->name, "push")) {
+ pragma_push();
+ } else if (!strcmp(tkidentifier->name, "pop")) {
+ pragma_pop();
+ } else if (!strcmp(tkidentifier->name, "parameter")) {
+ macrocheck = 1;
+ CMach_PragmaParams();
+ } else if (!strcmp(tkidentifier->name, "overload")) {
+ macrocheck = 1;
+ pragma_overload();
+ } else if (!strcmp(tkidentifier->name, "mark")) {
+ skipendofline();
+ macrocheck = 1;
+ return;
+ } else if (!strcmp(tkidentifier->name, "precompile_target")) {
+ pragma_precompile_target();
+ } else if (!strcmp(tkidentifier->name, "message")) {
+ pragma_message();
+ } else if (!strcmp(tkidentifier->name, "opt_unroll_count")) {
+ pragma_opt_unroll_count();
+ } else if (!strcmp(tkidentifier->name, "opt_unroll_instr_count")) {
+ pragma_opt_unroll_instr_count();
+ } else if (!strcmp(tkidentifier->name, "exception_terminate")) {
+ if (!preprocessing_only)
+ CExcept_Terminate();
+ } else if (!strcmp(tkidentifier->name, "exception_arrayinit")) {
+ if (!preprocessing_only)
+ CExcept_ArrayInit();
+ } else if (!strcmp(tkidentifier->name, "exception_magic")) {
+ if (!preprocessing_only)
+ CExcept_Magic();
+ } else if (!strcmp(tkidentifier->name, "SOMReleaseOrder")) {
+ macrocheck = 1;
+ CSOM_PragmaReleaseOrder();
+ } else if (!strcmp(tkidentifier->name, "SOMClassVersion")) {
+ macrocheck = 1;
+ CSOM_PragmaClassVersion();
+ } else if (!strcmp(tkidentifier->name, "SOMMetaClass")) {
+ macrocheck = 1;
+ CSOM_PragmaMetaClass();
+ } else if (!strcmp(tkidentifier->name, "SOMCallStyle")) {
+ CSOM_PragmaCallStyle();
+ } else {
+ for (opt = compileroptions; opt->name; opt++) {
+ if (!strcmp(tkidentifier->name, opt->name) && !(opt->bits & OPT_FLAG_4000)) {
+ pragma_on_off_reset(opt->bits);
+ if (opt->bits & OPT_FLAG_8000)
+ CMach_Configure();
+ goto foundOption;
+ }
+ }
+
+ save_eoltokens = cprep_eoltokens;
+ cprep_eoltokens = 1;
+ CodeGen_ParsePragma(tkidentifier);
+ cprep_eoltokens = save_eoltokens;
+ macrocheck = 1;
+ return;
+ }
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ skipendofline();
+ macrocheck = 1;
+ return;
+ }
+ foundOption:
+ if (notendofline()) {
+ CPrep_Error(113);
+ skipendofline();
+ }
+ CPrep_Reconfig();
+ macrocheck = 1;
+ }
+}
+
+static void prepinclude(Boolean flag) {
+ // mostly ok but registers need to be rearranged
+ short t;
+ Boolean r29;
+ short len;
+ short i;
+ char *save_pos;
+ char buf[256];
+ short start_tokenstacklevel;
+ StringPtr ptr;
+
+ if (!notendofline()) {
+ CPrep_Error(112);
+ return;
+ }
+
+ t = prepcurchar();
+ if (t != '"' && t != '<') {
+ CPrep_Error(117);
+ skipendofline();
+ return;
+ }
+
+ r29 = 1;
+ save_pos = pos;
+ if (t == '<') {
+ prepnextchar();
+ if (!copts.flat_include)
+ r29 = 0;
+ len = 0;
+ while ((t = prepnextstringchar(save_pos, 1)) != '>') {
+ if (t != 5) {
+ if (len > 254) {
+ CPrep_Error(106);
+ skipendofline();
+ return;
+ }
+ buf[++len] = t;
+ }
+ }
+ buf[0] = len;
+ ptr = (StringPtr) buf;
+ } else {
+ start_tokenstacklevel = tokenstacklevel;
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ buf[1] = 0;
+ if (t != TK_STRING) {
+ CPrep_Error(117);
+ skipendofline();
+ return;
+ }
+
+ while (t == TK_STRING) {
+ strncat(&buf[1], tkstring, 254 - strlen(&buf[1]));
+ buf[255] = 0;
+ if (tokenstacklevel == start_tokenstacklevel && !notendofline())
+ break;
+ macrocheck = 1;
+ t = plex();
+ macrocheck = 0;
+ }
+ buf[0] = strlen(&buf[1]);
+ ptr = (StringPtr) buf;
+ }
+
+ goendofline();
+ if (ismacroname4(CPrep_PragmaOnceName((StringPtr) buf, !r29)))
+ return;
+ if (flag || copts.always_import)
+ CPrep_DefinePragmaOnceMacro((StringPtr) buf, !r29);
+
+ if (copts.flat_include) {
+ for (i = len; i > 0; i--) {
+ switch (buf[i]) {
+ case ':':
+ case '/':
+ case '\\':
+ ptr = (StringPtr) buf;
+ ptr += i;
+ buf[i] = len - i;
+ goto all_done;
+ }
+ }
+ }
+
+all_done:
+ setupfile(ptr, r29, flag);
+}
+
+static void prepline() {
+ short t;
+ short len;
+ char buf[256];
+
+ cprep_hasprepline = 1;
+ if (!notendofline()) {
+ CPrep_Error(112);
+ return;
+ }
+
+ if (plex() != TK_INTCONST) {
+ CPrep_Error(117);
+ skipendofline();
+ return;
+ }
+
+ linenumber = CInt64_GetULong(&tkintconst) - 1;
+ if (notendofline()) {
+ if (prepnextchar() != '"') {
+ CPrep_Error(117);
+ skipendofline();
+ return;
+ }
+
+ len = 0;
+ while ((t = prepnextchar()) != '"') {
+ if (!t)
+ break;
+ if (len > 252) {
+ CPrep_Error(106);
+ skipendofline();
+ return;
+ }
+ buf[len] = t;
+ len++;
+ }
+ buf[len] = 0;
+
+ CTool_CtoPstr(buf);
+ filestack[filesp]->nameNode = CPrep_GetSourceFilePath(filestack[filesp]);
+ COS_FileSetFSSpec(&filestack[filesp]->textfile, (StringPtr) buf);
+ goendofline();
+ if (preprocessing_only && !copts.simple_prepdump)
+ CPrep_PreprocessDumpFileInfo(0);
+ }
+}
+
+static TypeIntegral *CPrep_GetPrepType(PrepValue *pv) {
+ if (copts.longlong_prepeval || copts.c9x) {
+ if (pv->is_unsigned)
+ return &stunsignedlonglong;
+ else
+ return &stsignedlonglong;
+ } else {
+ if (pv->is_unsigned)
+ return &stunsignedlong;
+ else
+ return &stsignedlong;
+ }
+}
+
+static PrepValue CPrep_ParseUnary() {
+
+}
+
+static PrepValue CPrep_ParseBinary(PrepValue *rhs, short op) {
+ // i need a lot of fixing :(
+ PrepValue a;
+ PrepValue b;
+ short t;
+ short op2;
+ short op3;
+ short prec2;
+ short prec3;
+
+ if (!rhs) {
+ a = CPrep_ParseUnary();
+ } else {
+ a = *rhs;
+ }
+
+ op2 = op;
+restart:
+ op3 = exprtk;
+ prec3 = GetPrec(op3);
+ if (!prec3) {
+ return a;
+ }
+ if (!notendofline()) {
+ CPrep_Error(112);
+ return a;
+ }
+ b = CPrep_ParseUnary();
+ prec3 = prec3; // variable change situation?
+ do {
+ if (exprtk == ')' || !notendofline()) {
+ if (b.is_unsigned)
+ a.is_unsigned = 1;
+ a.val = CMach_CalcIntDiadic((Type *) CPrep_GetPrepType(&a), a.val, t, b.val);
+ return a;
+ }
+
+ op = GetPrec(exprtk);
+ if (!op) {
+ CPrep_Error(141);
+ return a;
+ }
+ if (prec3 >= prec2) {
+ if (b.is_unsigned)
+ a.is_unsigned = 1;
+ a.val = CMach_CalcIntDiadic((Type *) CPrep_GetPrepType(&a), a.val, t, b.val);
+ if (GetPrec(op) > op2)
+ goto restart;
+ return a;
+ }
+ b = CPrep_ParseBinary(&b, prec3);
+ } while (1);
+}
+
+static PrepValue CPrep_ParseCond() {
+ PrepValue a;
+ PrepValue b;
+ PrepValue c;
+
+ a = CPrep_ParseBinary(NULL, -1);
+ if (exprtk == '?') {
+ b = CPrep_ParseCond();
+ if (!notendofline()) {
+ CPrep_Error(112);
+ return a;
+ }
+ if (exprtk != ':') {
+ CPrep_Error(170);
+ return a;
+ }
+ if (!notendofline()) {
+ CPrep_Error(112);
+ return a;
+ }
+ c = CPrep_ParseCond();
+ a = !CInt64_IsZero(&a.val) ? b : c;
+ }
+
+ return a;
+}
+
+static void doevalconstexpr() {
+ PrepValue v;
+
+ macrocheck = 1;
+ nlflag = 0;
+ cprep_incondexpr = 1;
+ v = CPrep_ParseCond();
+ if (exprtk)
+ CPrep_Error(141);
+ cprep_incondexpr = 0;
+ if (nlflag)
+ CPrep_Error(112);
+ else
+ goendofline();
+ tkintconst = v.val;
+}
+
+static void pushifstate(SInt16 state) {
+ if (iflevel >= 64) {
+ CPrep_Error(215);
+ } else {
+ ifstack[iflevel].state = state;
+ ifstack[iflevel].file = prep_file;
+ ifstack[iflevel].pos = pos - prep_file_start;
+ iflevel++;
+ }
+}
+
+static void popifstate() {
+ if (iflevel <= 0) {
+ CPrep_Error(117);
+ } else {
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ case IfState_3:
+ case IfState_4:
+ iflevel--;
+ return;
+ }
+
+ iflevel--;
+ if (iflevel > 0) {
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ case IfState_3:
+ case IfState_4:
+ prepifskip();
+ }
+ }
+ }
+}
+
+static void positiveif() {
+ pushifstate(IfState_0);
+}
+
+static void negativeif(Boolean flag) {
+ if (flag) {
+ pushifstate(IfState_1);
+ prepifskip();
+ } else {
+ pushifstate(IfState_3);
+ }
+}
+
+static void prepif() {
+ if (iflevel > 0) {
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ case IfState_3:
+ case IfState_4:
+ skipendofline();
+ negativeif(0);
+ return;
+ }
+ }
+
+ doevalconstexpr();
+ if (CInt64_IsZero(&tkintconst))
+ negativeif(1);
+ else
+ positiveif();
+}
+
+static void prepifdef() {
+ if (iflevel > 0) {
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ case IfState_3:
+ case IfState_4:
+ skipendofline();
+ negativeif(0);
+ return;
+ }
+ }
+
+ macrocheck = 0;
+ if (!notendofline()) {
+ CPrep_Error(112);
+ negativeif(1);
+ return;
+ }
+
+ if (lexidentifier() != TK_IDENTIFIER) {
+ CPrep_Error(107);
+ negativeif(1);
+ return;
+ }
+
+ macrocheck = 1;
+ goendofline();
+ if (ismacroname3())
+ positiveif();
+ else
+ negativeif(1);
+}
+
+static void prepifndef() {
+ if (iflevel > 0) {
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ case IfState_3:
+ case IfState_4:
+ skipendofline();
+ negativeif(0);
+ return;
+ }
+ }
+
+ macrocheck = 0;
+ if (!notendofline()) {
+ CPrep_Error(112);
+ negativeif(1);
+ return;
+ }
+
+ if (lexidentifier() != TK_IDENTIFIER) {
+ CPrep_Error(107);
+ negativeif(1);
+ return;
+ }
+
+ macrocheck = 1;
+ goendofline();
+ if (!ismacroname3())
+ positiveif();
+ else
+ negativeif(1);
+}
+
+static void prepelif() {
+ if (iflevel <= 0 || ifstack[iflevel - 1].state == IfState_2 || ifstack[iflevel - 1].state == IfState_4) {
+ CPrep_Error(118);
+ skipendofline();
+ return;
+ }
+
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ doevalconstexpr();
+ if (!CInt64_IsZero(&tkintconst))
+ ifstack[iflevel - 1].state = IfState_0;
+ break;
+ case IfState_3:
+ skipendofline();
+ break;
+ case IfState_0:
+ ifstack[iflevel - 1].state = IfState_3;
+ skipendofline();
+ prepifskip();
+ break;
+ default:
+#line 5700
+ CError_FATAL();
+ }
+}
+
+static void prepelse() {
+ if (iflevel <= 0 || ifstack[iflevel - 1].state == IfState_2 || ifstack[iflevel - 1].state == IfState_4) {
+ CPrep_Error(118);
+ skipendofline();
+ return;
+ }
+
+ if (!copts.ANSI_strict)
+ skipendofline();
+ else
+ goendofline();
+
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ ifstack[iflevel - 1].state = IfState_2;
+ break;
+ case IfState_0:
+ ifstack[iflevel - 1].state = IfState_4;
+ prepifskip();
+ break;
+ case IfState_3:
+ ifstack[iflevel - 1].state = IfState_4;
+ break;
+ default:
+#line 5738
+ CError_FATAL();
+ }
+}
+
+static void prependif() {
+ if (iflevel <= 0) {
+ CPrep_Error(118);
+ skipendofline();
+ return;
+ }
+
+ macrocheck = 0;
+ if (!copts.ANSI_strict)
+ skipendofline();
+ else
+ goendofline();
+
+ macrocheck = 1;
+ popifstate();
+}
+
+static void prepifskip() {
+ // this function does something very weird with its code generation that i can't match
+ TStreamElement ts;
+ short t;
+
+ while (iflevel > 0) {
+ switch (ifstack[iflevel - 1].state) {
+ case IfState_1:
+ case IfState_3:
+ case IfState_4:
+ restart:
+ t = prepskipnextchar();
+ pos = nextcharpos;
+ switch (t) {
+ case 0:
+ if (tokenstacklevel > 0) {
+ poptokenseq();
+ } else if (tokenstacklevel > 0 || pos >= prep_file_end) {
+ if (filesp > 0) {
+ popfile();
+ } else {
+ was_prep_error = 0;
+ ts.tokenfile = ifstack[iflevel - 1].file;
+ ts.tokenoffset = ifstack[iflevel - 1].pos;
+ CError_SetErrorToken(&ts);
+ CError_ErrorTerm(119);
+ iflevel = 0;
+ return;
+ }
+ } else {
+ CPrep_Error(105);
+ }
+ goto restart;
+ case '\r':
+ newline();
+ goto restart;
+ case '"':
+ skipendoflinematch(pos, '"');
+ goto restart;
+ case '\'':
+ skipendoflinematch(pos, '"');
+ goto restart;
+ case '#':
+ t = prepskipnextchar();
+ pos = nextcharpos;
+ switch (t) {
+ case '\r':
+ goto restart;
+ case 0:
+ CPrep_Error(102);
+ default:
+ pos = ReadIdentifier(pos - 1);
+ if (!strcmp("if", tkidentifier->name)) {
+ prepif();
+ } else if (!strcmp("ifdef", tkidentifier->name)) {
+ prepifdef();
+ } else if (!strcmp("ifndef", tkidentifier->name)) {
+ prepifndef();
+ } else if (!strcmp("elif", tkidentifier->name)) {
+ prepelif();
+ } else if (!strcmp("else", tkidentifier->name)) {
+ prepelse();
+ } else if (!strcmp("endif", tkidentifier->name)) {
+ prependif();
+ } else {
+ skipendofline();
+ goto restart;
+ }
+ }
+ break;
+ default:
+ skipendofline();
+ goto restart;
+ }
+ default:
+ return;
+ }
+ return;
+ }
+}
+
+void preprocessor() {
+ short t;
+
+ gDirectiveStart = pos - prep_file_start;
+ t = prepskipnextchar();
+ pos = nextcharpos;
+
+ switch (t) {
+ case 0:
+ CPrep_Error(102);
+ case '\r':
+ return;
+ }
+
+ pos = ReadIdentifier(pos - 1);
+ if (!strcmp("define", tkidentifier->name)) {
+ CPrep_Define();
+ macrocheck = 1;
+ return;
+ }
+ if (!strcmp("undef", tkidentifier->name)) {
+ prepundefine();
+ macrocheck = 1;
+ return;
+ }
+ if (!strcmp("include", tkidentifier->name)) {
+ prepinclude(0);
+ macrocheck = 1;
+ return;
+ }
+ if (!strcmp("line", tkidentifier->name)) {
+ prepline();
+ macrocheck = 1;
+ return;
+ }
+ if (!strcmp("error", tkidentifier->name)) {
+ CPrep_Error(318);
+ CError_ResetErrorSkip();
+ skipendofline();
+ macrocheck = 1;
+ return;
+ }
+ if (!strcmp("pragma", tkidentifier->name)) {
+ preppragma();
+ macrocheck = 1;
+ return;
+ }
+ if (!copts.ANSI_strict) {
+ if (!strcmp("warning", tkidentifier->name)) {
+ CPrep_Warning(337);
+ skipendofline();
+ macrocheck = 1;
+ return;
+ }
+ if (!strcmp(tkidentifier->name, "ident")) {
+ skipendofline();
+ macrocheck = 1;
+ return;
+ }
+ }
+ if (!strcmp("if", tkidentifier->name)) {
+ macrocheck = 1;
+ prepif();
+ return;
+ }
+ if (!strcmp("ifdef", tkidentifier->name)) {
+ macrocheck = 1;
+ prepifdef();
+ return;
+ }
+ if (!strcmp("ifndef", tkidentifier->name)) {
+ macrocheck = 1;
+ prepifndef();
+ return;
+ }
+ if (!strcmp("elif", tkidentifier->name)) {
+ macrocheck = 1;
+ prepelif();
+ return;
+ }
+ if (!strcmp("else", tkidentifier->name)) {
+ macrocheck = 1;
+ prepelse();
+ return;
+ }
+ if (!strcmp("endif", tkidentifier->name)) {
+ macrocheck = 1;
+ prependif();
+ return;
+ }
+ if (copts.objective_c || !copts.ANSI_strict) {
+ if (!strcmp("import", tkidentifier->name)) {
+ prepinclude(1);
+ macrocheck = 1;
+ return;
+ }
+ }
+ CPrep_Error(104);
+ skipendofline();
+ macrocheck = 1;
+}
+
+SInt32 CPrep_BrowserTokenOffset(FileOffsetInfo *foi) {
+ return foi->tokenoffset;
+}
+
+SInt32 CPrep_BrowserFileOffset() {
+ if (ts_first < ts_current)
+ return ts_current[-1].tokenoffset + 1;
+ else if (tokenstacklevel)
+ return tokenstack[0].pos - filestack[filesp]->textbuffer;
+ else
+ return pos - filestack[filesp]->textbuffer;
+}
void CPrep_BrowserFilePosition(CPrepFileInfo **fileinfo, SInt32 *offset) {
CPrepFileInfo *file;
diff --git a/compiler_and_linker/FrontEnd/C/CPrepTokenizer.c b/compiler_and_linker/FrontEnd/C/CPrepTokenizer.c
index 5b77268..62753f8 100644
--- a/compiler_and_linker/FrontEnd/C/CPrepTokenizer.c
+++ b/compiler_and_linker/FrontEnd/C/CPrepTokenizer.c
@@ -1,156 +1,1889 @@
#include "compiler.h"
#include "compiler/tokens.h"
+#include "compiler/CError.h"
+#include "compiler/CInt64.h"
+#include "cos.h"
static Boolean prepnextstringchar_foundnl;
+#define UCD (unsigned char *)
+#define CD (char *)
+
short prepskipnextchar() {
+ short c;
+ unsigned char *start;
+ unsigned char *p;
+
+ start = UCD pos;
+ p = UCD pos;
+loop:
+ switch ((c = *p)) {
+ case 0:
+ if (tokenstacklevel > 0 || CD p >= prep_file_end) {
+ pos = CD p;
+ nextcharpos = CD p;
+ return c;
+ } else {
+ pos = CD p++;
+ nextcharpos = CD p;
+ return c;
+ }
+ case 4:
+ case 5:
+ p++;
+ goto loop;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ spaceskip = 1;
+ p++;
+ goto loop;
+ case ';':
+ pos = CD p++;
+ if (tokenstacklevel <= 0 && in_assembler && copts.asmsemicolcomment) {
+ spaceskip = 1;
+ nextcharpos = CPrep_SkipNewComment(CD p);
+ return CPrep_SkipNewCommentChar;
+ }
+ nextcharpos = CD p;
+ return c;
+ case '#':
+ pos = CD p++;
+ if (tokenstacklevel <= 0 && in_assembler && copts.asmpoundcomment) {
+ spaceskip = 1;
+ nextcharpos = CPrep_SkipNewComment(CD p);
+ return CPrep_SkipNewCommentChar;
+ }
+ nextcharpos = CD p;
+ return c;
+ case '/':
+ pos = CD p++;
+ if (copts.multibyteaware) {
+ while (p[0] == '\\' && !COS_IsMultiByte(CD start, CD p) && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ } else {
+ while (p[0] == '\\' && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ }
+ if (tokenstacklevel <= 0) {
+ if (p[0] == '/' && (!copts.ANSI_strict || copts.cplusplus || copts.c9x)) {
+ spaceskip = 1;
+ nextcharpos = CPrep_SkipNewComment(CD p + 1);
+ return CPrep_SkipNewCommentChar;
+ } else if (p[0] == '*') {
+ spaceskip = 1;
+ p++;
+ for (;;) {
+ if (!(c = *(p++))) {
+ if (tokenstacklevel > 0 || CD p >= prep_file_end) {
+ CPrep_Error(103);
+ nextcharpos = CD p - 1;
+ return c;
+ }
+ p[-1] = ' ';
+ }
+ if (c == '*') {
+ if (copts.multibyteaware) {
+ while (p[0] == '\\' && !COS_IsMultiByte(CD start, CD p) && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ } else {
+ while (p[0] == '\\' && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ }
+ if (*p == '/') {
+ p++;
+ goto loop;
+ }
+ }
+ if (c == '\r')
+ foundnl();
+ }
+ }
+ }
+ nextcharpos = CD p;
+ return c;
+ case '%':
+ pos = CD p++;
+ if (*p == ':' && copts.cplusplus) {
+ nextcharpos = CD p + 1;
+ return '#';
+ }
+ nextcharpos = CD p;
+ return c;
+ case '\\':
+ pos = CD p++;
+ mid_backslash:
+ if (*p == '\r') {
+ if (!copts.multibyteaware || !COS_IsMultiByte(CD start, CD p - 1)) {
+ foundnl();
+ if (p[1] == '\n')
+ p += 2;
+ else
+ p += 1;
+ goto loop;
+ }
+ }
+ nextcharpos = CD p;
+ return c;
+ case '?':
+ pos = CD p++;
+ if (copts.trigraphs && p[0] == '?') {
+ switch (p[1]) {
+ case '=':
+ nextcharpos = CD p + 2;
+ return '#';
+ case '/':
+ c = '\\';
+ p += 2;
+ goto mid_backslash;
+ case '\'':
+ nextcharpos = CD p + 2;
+ return '^';
+ case '(':
+ nextcharpos = CD p + 2;
+ return '[';
+ case ')':
+ nextcharpos = CD p + 2;
+ return ']';
+ case '!':
+ nextcharpos = CD p + 2;
+ return '|';
+ case '<':
+ nextcharpos = CD p + 2;
+ return '{';
+ case '>':
+ nextcharpos = CD p + 2;
+ return '}';
+ case '-':
+ nextcharpos = CD p + 2;
+ return '~';
+ }
+ }
+ nextcharpos = CD p;
+ return c;
+ default:
+ pos = CD p++;
+ nextcharpos = CD p;
+ return c;
+ }
}
short prepnextchar() {
+ short c;
+ unsigned char *start;
+ unsigned char *p;
+
+ start = UCD pos;
+ p = UCD pos;
+loop:
+ switch ((c = *(p++))) {
+ case 0:
+ pos = CD p - 1;
+ return c;
+ case '/':
+ if (copts.multibyteaware) {
+ while (p[0] == '\\' && !COS_IsMultiByte(CD start, CD p) && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ } else {
+ while (p[0] == '\\' && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ }
+ if (p[0] == '/' && (!copts.ANSI_strict || copts.cplusplus)) {
+ spaceskip = 1;
+ pos = CPrep_SkipNewComment(CD p + 1);
+ return CPrep_SkipNewCommentChar;
+ } else if (p[0] == '*') {
+ spaceskip = 1;
+ p++;
+ for (;;) {
+ if (!(c = *(p++))) {
+ if (tokenstacklevel > 0 || CD p >= prep_file_end) {
+ pos = CD p - 1;
+ CPrep_Error(103);
+ return c;
+ }
+ p[-1] = ' ';
+ }
+ if (c == '*') {
+ if (copts.multibyteaware) {
+ while (p[0] == '\\' && !COS_IsMultiByte(CD start, CD p) && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ } else {
+ while (p[0] == '\\' && p[1] == '\r') {
+ foundnl();
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ }
+ }
+ if (*p == '/')
+ break;
+ }
+ if (c == '\r')
+ foundnl();
+ }
+ pos = CD p + 1;
+ return ' ';
+ } else {
+ pos = CD p;
+ return c;
+ }
+ case '\\':
+ backslash:
+ if (*p == '\r') {
+ if (!copts.multibyteaware || !COS_IsMultiByte(CD start, CD p - 1)) {
+ foundnl();
+ if (p[1] == '\n')
+ p += 2;
+ else
+ p += 1;
+ goto loop;
+ }
+ }
+ pos = CD p;
+ return c;
+ case '%':
+ if (*p == ':' && copts.cplusplus) {
+ pos = CD p + 1;
+ return '#';
+ }
+ pos = CD p;
+ return c;
+ case '?':
+ if (copts.trigraphs && p[0] == '?') {
+ switch (p[1]) {
+ case '=':
+ pos = CD p + 2;
+ return '#';
+ case '/':
+ c = '\\';
+ p += 2;
+ goto backslash;
+ case '\'':
+ pos = CD p + 2;
+ return '^';
+ case '(':
+ pos = CD p + 2;
+ return '[';
+ case ')':
+ pos = CD p + 2;
+ return ']';
+ case '!':
+ pos = CD p + 2;
+ return '|';
+ case '<':
+ pos = CD p + 2;
+ return '{';
+ case '>':
+ pos = CD p + 2;
+ return '}';
+ case '-':
+ pos = CD p + 2;
+ return '~';
+ }
+ }
+ pos = CD p;
+ return c;
+ default:
+ pos = CD p;
+ return c;
+ }
}
short prepnextstringchar(char *str, Boolean flag) {
+ unsigned char *p;
+ short c;
+ p = UCD pos;
+
+loop:
+ switch ((c = *(p++))) {
+ case 0:
+ pos = CD p - 1;
+ return c;
+ case '\\':
+ backslash:
+ if (p[0] == '\r' && (!copts.multibyteaware || !COS_IsMultiByte(str, CD p - 1))) {
+ if (flag)
+ foundnl();
+ else
+ prepnextstringchar_foundnl = 1;
+ if (p[1] == '\n')
+ p += 2;
+ else
+ p += 1;
+ goto loop;
+ }
+ pos = CD p;
+ return c;
+ case '?':
+ if (copts.trigraphs && p[0] == '?') {
+ switch (p[1]) {
+ case '=':
+ pos = CD p + 2;
+ return '#';
+ case '/':
+ c = '\\';
+ p += 2;
+ goto backslash;
+ case '\'':
+ pos = CD p + 2;
+ return '^';
+ case '(':
+ pos = CD p + 2;
+ return '[';
+ case ')':
+ pos = CD p + 2;
+ return ']';
+ case '!':
+ pos = CD p + 2;
+ return '|';
+ case '<':
+ pos = CD p + 2;
+ return '{';
+ case '>':
+ pos = CD p + 2;
+ return '}';
+ case '-':
+ pos = CD p + 2;
+ return '~';
+ }
+ }
+ pos = CD p;
+ return c;
+ default:
+ pos = CD p;
+ return c;
+ }
}
void CPrep_MatchChar(char ch, Boolean flag) {
+ char *p;
+ char *start;
+ char c;
+ Boolean r26;
+
+ p = start = pos;
+ r26 = 0;
+loop:
+ if (!(c = *(p++))) {
+ if (tokenstacklevel > 0 || p >= prep_file_end)
+ CPrep_Error(102);
+ else if (ch == '"')
+ CPrep_Error(101);
+ else if (ch == '\'')
+ CPrep_Error(100);
+ CPrep_Error(117);
+ pos = p - 1;
+ return;
+ }
+
+ if (c == '\r') {
+ if (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1)) {
+ if (flag)
+ foundnl();
+ if (*p == '\n')
+ p++;
+ CPrep_Error(112);
+ pos = p;
+ return;
+ }
+ r26 = 0;
+ goto loop;
+ }
+
+ if (c == '?' && p[0] == '?' && copts.trigraphs) {
+ switch (p[1]) {
+ case '!':
+ case '\'':
+ case '(':
+ case ')':
+ case '-':
+ case '<':
+ case '=':
+ case '>':
+ r26 = 0;
+ p += 2;
+ goto loop;
+ case '/':
+ p += 2;
+ goto backslash;
+ }
+ }
+
+ if (c == '\\' && !r26 && (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1))) {
+ backslash:
+ if (*p == '\r') {
+ if (flag)
+ foundnl();
+ if (*(++p) == '\n')
+ p++;
+ r26 = 0;
+ } else {
+ r26 = 1;
+ }
+ goto loop;
+ }
+
+ if (c == ch && !r26) {
+ pos = p;
+ } else {
+ r26 = 0;
+ goto loop;
+ }
}
-char *CPrep_MatchChar2(char *str, char ch, Boolean flag) {
+char *CPrep_MatchChar2(char *start, char ch, Boolean flag) {
+ char *p;
+ char c;
+ Boolean r28;
+
+ p = start;
+ r28 = 0;
+loop:
+ if (!(c = *(p++))) {
+ if (tokenstacklevel > 0 || p >= prep_file_end)
+ CPrep_Error(102);
+ else if (ch == '"')
+ CPrep_Error(101);
+ else if (ch == '\'')
+ CPrep_Error(100);
+ CPrep_Error(117);
+ return p - 1;
+ }
+
+ if (c == '\r') {
+ if (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1)) {
+ if (flag)
+ foundnl();
+ if (*p == '\n')
+ p++;
+ CPrep_Error(112);
+ return p;
+ }
+ r28 = 0;
+ goto loop;
+ }
+
+ if (c == '?' && p[0] == '?' && copts.trigraphs) {
+ switch (p[1]) {
+ case '!':
+ case '\'':
+ case '(':
+ case ')':
+ case '-':
+ case '<':
+ case '=':
+ case '>':
+ r28 = 0;
+ p += 2;
+ goto loop;
+ case '/':
+ p += 2;
+ goto backslash;
+ }
+ }
+
+ if (c == '\\' && !r28 && (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1))) {
+ backslash:
+ if (*p == '\r') {
+ if (flag)
+ foundnl();
+ if (*(++p) == '\n')
+ p++;
+ r28 = 0;
+ } else {
+ r28 = 1;
+ }
+ goto loop;
+ }
+
+ if (c == ch && !r28) {
+ return p;
+ } else {
+ r28 = 0;
+ goto loop;
+ }
}
short prepcurchar() {
+ char *save_pos;
+ short t;
+
+ save_pos = pos;
+ t = prepnextchar();
+ nextcharpos = pos;
+ pos = save_pos;
+ return t;
}
static short prepcurstringchar(char *str) {
+ char *save_pos;
+ short t;
+
+ save_pos = pos;
+ prepnextstringchar_foundnl = 0;
+ t = prepnextstringchar(str, 0);
+ nextcharpos = pos;
+ pos = save_pos;
+
+ return t;
}
static void prepcurstringchar_skip() {
+ pos = nextcharpos;
+ if (prepnextstringchar_foundnl)
+ foundnl();
}
-char *ReadIdentifier(char *str) {
+char *ReadIdentifier(char *p) {
+ char buf[256];
+ char *start;
+ int len;
+
+ start = p;
+ len = 0;
+loop:
+ for (;;) {
+ if (!cprep_idarray[(unsigned char) *p])
+ break;
+ if (len < 255)
+ buf[len++] = *p;
+ p++;
+ }
+
+ if (copts.multibyteaware) {
+ if ((unsigned char) *p == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ foundnl();
+ goto loop;
+ }
+ } else {
+ if ((unsigned char) *p == '\\' && p[1] == '\r') {
+ if (p[2] == '\n')
+ p += 3;
+ else
+ p += 2;
+ foundnl();
+ goto loop;
+ }
+ }
+
+ buf[len] = 0;
+ tkidentifier = GetHashNameNodeExport(buf);
+ return p;
}
static short intsuffix(short token, Boolean flag) {
+ Boolean is_unsigned;
+ Boolean is_long;
+ Boolean is_longlong;
+ short t;
+
+ is_unsigned = is_long = is_longlong = 0;
+ t = token;
+ switch (t) {
+ case 'u':
+ case 'U':
+ is_unsigned = 1;
+ pos = nextcharpos;
+ t = prepcurchar();
+ if (t == 'l' || t == 'L') {
+ is_long = 1;
+ pos = nextcharpos;
+ t = *pos;
+ if (copts.longlong) {
+ pos = nextcharpos;
+ t = prepcurchar();
+ if (t == 'l' || t == 'L') {
+ is_longlong = 1;
+ pos = nextcharpos;
+ t = *pos;
+ }
+ }
+ }
+ break;
+ case 'l':
+ case 'L':
+ is_long = 1;
+ pos = nextcharpos;
+ t = prepcurchar();
+ if (t == 'u' || t == 'U') {
+ is_unsigned = 1;
+ pos = nextcharpos;
+ t = *pos;
+ } else if (copts.longlong && (t == 'l' || t == 'L')) {
+ is_longlong = 1;
+ pos = nextcharpos;
+ t = prepcurchar();
+ if (t == 'u' || t == 'U') {
+ is_unsigned = 1;
+ pos = nextcharpos;
+ t = *pos;
+ }
+ }
+ break;
+ case 'i':
+ case 'I':
+ if (copts.cpp_extensions && !copts.ANSI_strict && copts.longlong) {
+ pos = nextcharpos;
+ t = prepcurchar();
+ if (t == '6') {
+ pos = nextcharpos;
+ t = prepcurchar();
+ if (t == '4') {
+ is_long = is_longlong = 1;
+ pos = nextcharpos;
+ t = *pos;
+ }
+ }
+ }
+ break;
+ case 'b':
+ case 'B':
+ case 'f':
+ case 'F':
+ if (InlineAsm_gccmode)
+ return IT_INT;
+ break;
+ }
+
+ if ((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z') || (t == '_') || (t >= '0' && t <= '9'))
+ CPrep_Error(105);
+
+ if (!is_longlong && !is_long) {
+ if (!is_unsigned && CInt64_IsInRange(tkintconst, stsignedint.size))
+ return IT_INT;
+ if ((flag || is_unsigned) && CInt64_IsInURange(tkintconst, stunsignedint.size))
+ return IT_UINT;
+ }
+ if (!is_longlong) {
+ if (!is_unsigned && CInt64_IsInRange(tkintconst, stsignedlong.size))
+ return IT_LONG;
+ if (CInt64_IsInURange(tkintconst, stunsignedlong.size))
+ return IT_ULONG;
+ }
+ if (copts.longlong) {
+ if (!is_unsigned && CInt64_IsInRange(tkintconst, stsignedlonglong.size))
+ return IT_LONGLONG;
+ if (CInt64_IsInURange(tkintconst, stsignedlonglong.size))
+ return IT_ULONGLONG;
+ }
+ CError_Error(154);
+ tkintconst = cint64_zero;
+ return IT_INT;
}
static short floatsuffix(short token) {
+ short whichtype;
+
+ switch (token) {
+ case 'f':
+ case 'F':
+ pos = nextcharpos;
+ token = *pos;
+ whichtype = IT_FLOAT;
+ if (stfloat.size != stlongdouble.size)
+ tkfloatconst = CMach_CalcFloatConvert((Type *) &stfloat, tkfloatconst);
+ break;
+ case 'l':
+ case 'L':
+ pos = nextcharpos;
+ token = *pos;
+ whichtype = IT_LONGDOUBLE;
+ break;
+ case 'd':
+ case 'D':
+ if (!copts.ANSI_strict) {
+ pos = nextcharpos;
+ token = *pos;
+ whichtype = IT_DOUBLE;
+ if (stdouble.size != stlongdouble.size)
+ tkfloatconst = CMach_CalcFloatConvert((Type *) &stdouble, tkfloatconst);
+ }
+ break;
+ default:
+ if (copts.float_constants) {
+ whichtype = IT_FLOAT;
+ if (stfloat.size != stlongdouble.size)
+ tkfloatconst = CMach_CalcFloatConvert((Type *) &stfloat, tkfloatconst);
+ } else {
+ whichtype = IT_DOUBLE;
+ if (stdouble.size != stlongdouble.size)
+ tkfloatconst = CMach_CalcFloatConvert((Type *) &stdouble, tkfloatconst);
+ }
+ }
+
+ if ((token >= 'a' && token <= 'z') || (token >= 'A' && token <= 'Z') || (token == '_') || (token >= '0' && token <= '9')) {
+ CPrep_Error(105);
+ whichtype = IT_DOUBLE;
+ }
+
+ return whichtype;
}
static short tohex(short token) {
+ if (token >= '0' && token <= '9')
+ return token - '0';
+ if (token >= 'a' && token <= 'f')
+ return token - 'a' + 10;
+ if (token >= 'A' && token <= 'F')
+ return token - 'A' + 10;
+ return -1;
}
-static short nextchar(char *str) {
+static SInt32 nextchar(char *str) {
+ // minor register allocation issues
+ SInt32 chr_max;
+ short tmpchr;
+ SInt32 chr;
+ Boolean out_of_bounds;
+ short i;
+ short t;
+
+ chr_max = 0xFF;
+ if (widestring) chr_max = 0xFFFF;
+
+ was_escchar = 0;
+ t = prepnextstringchar(str, 1);
+
+ if (t == '\\' && (!copts.multibyteaware || !COS_IsMultiByte(str, pos - 1))) {
+ was_escchar = 1;
+ t = prepnextstringchar(str, 1);
+ switch (t) {
+ case 'a': return 7;
+ case 'b': return 8;
+ case 't': return 9;
+ case 'v': return 11;
+ case 'f': return 12;
+ case 'n':
+ if (copts.mpwc_newline)
+ return 13;
+ else
+ return 10;
+ case 'r':
+ if (copts.mpwc_newline)
+ return 10;
+ else
+ return 13;
+ case 'e': return 27;
+ case 'x':
+ chr = tohex(prepnextstringchar(str, 1));
+ if (chr == -1) {
+ CPrep_Error(100);
+ return ' ';
+ }
+ out_of_bounds = 0;
+ while (tohex(tmpchr = prepcurstringchar(str)) != -1) {
+ chr = (chr << 4) + tohex(tmpchr);
+ prepcurstringchar_skip();
+ if (chr & ~chr_max)
+ out_of_bounds = 1;
+ }
+ if (out_of_bounds)
+ CError_Error(100);
+ break;
+ default:
+ if (t >= '0' && t <= '7') {
+ out_of_bounds = 0;
+ i = 1;
+ chr = t - '0';
+ while (i < 3 && (tmpchr = prepcurstringchar(str)) >= '0' && tmpchr <= '9') {
+ chr = (chr << 3) + (tmpchr - '0');
+ prepcurstringchar_skip();
+ if (chr & ~chr_max)
+ out_of_bounds = 1;
+ i++;
+ }
+ if (out_of_bounds)
+ CError_Error(100);
+ } else {
+ chr = t;
+ }
+ }
+ } else {
+ chr = t;
+ }
+
+ if (chr_max == 0xFF)
+ return (char) (chr & chr_max);
+ else
+ return (chr & chr_max);
}
char *CPrep_SkipNewComment(char *str) {
-
}
-Boolean skipendoflinematch(char *str, Boolean flag) {
+Boolean skipendoflinematch(char *str, short token) {
}
void skipendofline() {
}
void CPrep_SkipAsmComment() {
+ Boolean save_macrocheck = macrocheck;
+ skipendofline();
+ macrocheck = save_macrocheck;
+}
+
+static short tille() { return TK_NEG6; }
+
+static short tcret() {
+ newline();
+ if (cprep_eoltokens)
+ return TK_NEG7;
+ else
+ return 0;
+}
+
+static short tapos() {
+ // has register allocation issues
+ UInt32 maxvalue;
+ int bytecount;
+ CInt64 ci58;
+ CInt64 ci50;
+ CInt64 ci48;
+ SInt32 t;
+ SInt32 t2;
+ int i;
+ char *start;
+
+ start = pos;
+ t = nextchar(pos);
+ if ((t == '\'' || t == 0 || t == '\r') && !was_escchar) {
+ CPrep_Error(100);
+ tkintconst = cint64_zero;
+ tksize = IT_INT;
+ return TK_INTCONST;
+ }
+
+ t2 = nextchar(start);
+ if (t2 == '\'' && !was_escchar) {
+ if (widestring) {
+ switch (stwchar.size) {
+ case 1:
+ CInt64_SetULong(&tkintconst, (UInt8) t);
+ tksize = copts.cplusplus ? IT_SCHAR : IT_INT;
+ break;
+ case 2:
+ CInt64_SetULong(&tkintconst, (UInt16) t);
+ tksize = IT_UINT;
+ break;
+ case 4:
+ CInt64_SetULong(&tkintconst, (UInt32) t);
+ tksize = IT_UINT;
+ break;
+ default:
+#line 1386
+ CError_FATAL();
+ }
+ } else {
+ if (copts.unsignedchars)
+ t &= 0xFF;
+ CInt64_SetLong(&tkintconst, t);
+ tksize = copts.cplusplus ? IT_SCHAR : IT_INT;
+ }
+ } else {
+ if (widestring) {
+ switch (stwchar.size) {
+ case 1:
+ CInt64_SetULong(&ci50, 8);
+ maxvalue = 0xFF;
+ bytecount = 1;
+ break;
+ case 2:
+ CInt64_SetULong(&ci50, 16);
+ maxvalue = 0xFFFF;
+ bytecount = 2;
+ break;
+ case 4:
+ CInt64_SetULong(&ci50, 32);
+ maxvalue = 0xFFFFFFFF;
+ bytecount = 4;
+ break;
+ default:
+#line 1424
+ CError_FATAL();
+ }
+ } else {
+ CInt64_SetULong(&ci50, 8);
+ maxvalue = 0xFF;
+ bytecount = 1;
+ }
+
+ CInt64_SetULong(&tkintconst, t & maxvalue);
+ i = bytecount;
+ do {
+ if ((t2 == 0 || t2 == '\r') && !was_escchar) {
+ CPrep_Error(100);
+ goto after_char_const;
+ }
+ CInt64_SetULong(&ci48, t2 & maxvalue);
+ ci58 = CInt64_Shl(tkintconst, ci50);
+ tkintconst = CInt64_Or(ci58, ci48);
+ i += bytecount;
+ t2 = nextchar(start);
+ if (t2 == '\'' && !was_escchar)
+ goto after_char_const;
+ } while (i < stunsignedlonglong.size);
+ CPrep_Error(100);
+ after_char_const:
+ if (i <= stunsignedint.size && i < stunsignedlong.size)
+ tksize = IT_UINT;
+ else if (i <= stunsignedlong.size)
+ tksize = IT_ULONG;
+ else
+ tksize = IT_ULONGLONG;
+ }
+
+ return TK_INTCONST;
+}
+
+static short tquot() {
+ // has register allocation issues
+ TypeIntegral *type; // r22
+ char *string_ptr; // r21
+ SInt32 r20; // r20
+ char *save_pos; // r19
+ short c; // r19
+ char *start_pos; // r18
+ CInt64 ch64;
+
+ start_pos = pos;
+ at_linestart = 0;
+ if (cprep_nostring)
+ return '"';
+
+ string_ptr = *stringmem;
+ ispascalstring = 0;
+ r20 = 0;
+ if (widestring)
+ type = &stwchar;
+ else
+ type = &stchar;
+
+ if (prepcurstringchar(start_pos) == '\\') {
+ save_pos = pos;
+ prepcurstringchar_skip();
+ if (prepcurstringchar(start_pos) == 'p') {
+ prepcurstringchar_skip();
+ ispascalstring = 1;
+ string_ptr += type->size;
+ } else {
+ pos = save_pos;
+ }
+ }
+
+ do {
+ c = nextchar(start_pos);
+ if ((c == '"' || c == '\r' || c == 0) && !was_escchar) {
+ if (c == 0 && (tokenstacklevel > 0 || pos >= prep_file_end))
+ CPrep_Error(102);
+ else if (c != '"')
+ CPrep_Error(101);
+ break;
+ }
+ if ((r20 + type->size) >= maxstringsize) {
+ string_ptr = (char *) (string_ptr - *stringmem);
+ if (!COS_ResizeHandle(stringmem, maxstringsize += 256))
+ CError_NoMem();
+ string_ptr = *stringmem + (SInt32) string_ptr;
+ }
+ if (type->size != 1) {
+ CInt64_SetLong(&ch64, c);
+ CMach_InitIntMem((Type *) type, ch64, string_ptr);
+ string_ptr += type->size;
+ r20 += type->size;
+ } else {
+ *string_ptr = c;
+ string_ptr++;
+ r20++;
+ }
+ } while (1);
+
+ if (ispascalstring) {
+ if (r20 > 255 && type->size == 1) {
+ CPrep_Error(106);
+ r20 = 255;
+ }
+ CInt64_SetLong(&ch64, r20 / type->size);
+ CMach_InitIntMem((Type *) type, ch64, *stringmem);
+ r20 += type->size;
+ } else {
+ if ((r20 + 1) >= maxstringsize) {
+ if (!COS_ResizeHandle(stringmem, maxstringsize += 256))
+ CError_NoMem();
+ CMach_InitIntMem((Type *) type, cint64_zero, *stringmem + r20);
+ r20 += type->size;
+ }
+ }
+
+ tksize = r20;
+ tkstring = galloc(r20);
+ memcpy(tkstring, *stringmem, tksize);
+ if (widestring)
+ return TK_STRING_WIDE;
+ else
+ return TK_STRING;
+}
+
+static short thash() {
+ if (at_linestart) {
+ preprocessor();
+ return 0;
+ }
+ return '#';
+}
+
+static short tmult() {
+ at_linestart = 0;
+ if (prepcurchar() == '=') {
+ pos = nextcharpos;
+ return TK_MULT_ASSIGN;
+ }
+ return '*';
+}
+
+static short tcolo() {
+ char t2;
+ at_linestart = 0;
+ if (copts.cplusplus) {
+ t2 = prepcurchar();
+ if (t2 == ':') {
+ pos = nextcharpos;
+ return TK_COLON_COLON;
+ }
+ if (t2 == '>' && !preprocessing_only) {
+ pos = nextcharpos;
+ return ']';
+ }
+ }
+ return ':';
+}
+
+static short tless() {
+ short t2;
+ at_linestart = 0;
+ t2 = prepcurchar();
+ if (t2 == '=') {
+ pos = nextcharpos;
+ return TK_LESS_EQUAL;
+ }
+ if (t2 == '<') {
+ pos = nextcharpos;
+ if (prepcurchar() == '=') {
+ pos = nextcharpos;
+ return TK_SHL_ASSIGN;
+ } else {
+ return TK_SHL;
+ }
+ }
+ if (t2 == '%' && copts.cplusplus && !preprocessing_only) {
+ pos = nextcharpos;
+ return '{';
+ }
+ if (t2 == ':' && copts.cplusplus && !preprocessing_only) {
+ pos = nextcharpos;
+ return '[';
+ }
+ return '<';
+}
+
+static short tequa(short) {
+ at_linestart = 0;
+ if (prepcurchar() == '=') {
+ pos = nextcharpos;
+ return TK_LOGICAL_EQ;
+ }
+ return '=';
+}
+
+static short tgrea(short) {
+ short t2;
+ at_linestart = 0;
+ t2 = prepcurchar();
+ if (t2 == '=') {
+ pos = nextcharpos;
+ return TK_GREATER_EQUAL;
+ }
+ if (t2 == '>') {
+ pos = nextcharpos;
+ if (prepcurchar() == '=') {
+ pos = nextcharpos;
+ return TK_SHR_ASSIGN;
+ } else {
+ return TK_SHR;
+ }
+ }
+ return '>';
+}
+
+static short tatsg(short) {
+ char *start_pos;
+ Boolean save_idarray;
+
+ start_pos = pos;
+ at_linestart = 0;
+
+ if (copts.objective_c || in_assembler) {
+ save_idarray = cprep_idarray['@'];
+ cprep_idarray['@'] = 1;
+ pos = ReadIdentifier(start_pos - 1);
+ cprep_idarray['@'] = save_idarray;
+
+ if (copts.objective_c) {
+ if (!strcmp("@interface", tkidentifier->name))
+ return TK_AT_INTERFACE;
+ if (!strcmp("@implementation", tkidentifier->name))
+ return TK_AT_IMPLEMENTATION;
+ if (!strcmp("@protocol", tkidentifier->name))
+ return TK_AT_PROTOCOL;
+ if (!strcmp("@end", tkidentifier->name))
+ return TK_AT_END;
+ if (!strcmp("@private", tkidentifier->name))
+ return TK_AT_PRIVATE;
+ if (!strcmp("@protected", tkidentifier->name))
+ return TK_AT_PROTECTED;
+ if (!strcmp("@public", tkidentifier->name))
+ return TK_AT_PUBLIC;
+ if (!strcmp("@class", tkidentifier->name))
+ return TK_AT_CLASS;
+ if (!strcmp("@selector", tkidentifier->name))
+ return TK_AT_SELECTOR;
+ if (!strcmp("@encode", tkidentifier->name))
+ return TK_AT_ENCODE;
+ if (!strcmp("@defs", tkidentifier->name))
+ return TK_AT_DEFS;
+ }
+
+ if (in_assembler)
+ return TK_IDENTIFIER;
+
+ pos = start_pos;
+ }
+
+ return '@';
+}
+
+static short tperc(short) {
+ char t2;
+ at_linestart = 0;
+ t2 = prepcurchar();
+ if (t2 == '=') {
+ pos = nextcharpos;
+ return TK_MOD_ASSIGN;
+ }
+ if (t2 == '>' && copts.cplusplus && !preprocessing_only) {
+ pos = nextcharpos;
+ return '}';
+ }
+ return '%';
+}
+
+static short texcl() {
+ at_linestart = 0;
+ if (prepcurchar() == '=') {
+ pos = nextcharpos;
+ return TK_LOGICAL_NE;
+ }
+ return '!';
+}
+
+static short tplus() {
+ short t2;
+ at_linestart = 0;
+ t2 = prepcurchar();
+ if (t2 == '=') {
+ pos = nextcharpos;
+ return TK_ADD_ASSIGN;
+ }
+ if (t2 == '+') {
+ pos = nextcharpos;
+ return TK_INCREMENT;
+ }
+ return '+';
+}
+
+static short tminu() {
+ short t2;
+ at_linestart = 0;
+ t2 = prepcurchar();
+ if (t2 == '=') {
+ pos = nextcharpos;
+ return TK_SUB_ASSIGN;
+ }
+ if (t2 == '-') {
+ pos = nextcharpos;
+ return TK_DECREMENT;
+ }
+ if (t2 == '>') {
+ pos = nextcharpos;
+ if (copts.cplusplus && prepcurchar() == '*') {
+ pos = nextcharpos;
+ return TK_ARROW_STAR;
+ }
+ return TK_ARROW;
+ }
+ return '-';
+}
+
+static short torrr() {
+ short t2;
+ at_linestart = 0;
+ t2 = prepcurchar();
+ if (t2 == '=') {
+ pos = nextcharpos;
+ return TK_OR_ASSIGN;
+ }
+ if (t2 == '|') {
+ pos = nextcharpos;
+ return TK_LOGICAL_OR;
+ }
+ return '|';
+}
+
+static short tampe() {
+ short t2;
+ at_linestart = 0;
+ t2 = prepcurchar();
+ if (t2 == '=') {
+ pos = nextcharpos;
+ return TK_AND_ASSIGN;
+ }
+ if (t2 == '&') {
+ pos = nextcharpos;
+ return TK_LOGICAL_AND;
+ }
+ return '&';
+}
+
+static short tpowe() {
+ at_linestart = 0;
+ if (prepcurchar() == '=') {
+ pos = nextcharpos;
+ return TK_XOR_ASSIGN;
+ }
+ return '^';
+}
+
+static short tdivi() {
+ at_linestart = 0;
+ if (prepcurchar() == '=') {
+ pos = nextcharpos;
+ return TK_DIV_ASSIGN;
+ }
+ return '/';
}
-static short tille() {}
-static short tcret() {}
-static short tapos() {}
-static short tquot() {}
-static short thash() {}
-static short tmult() {}
-static short tcolo() {}
-static short tless() {}
-static short tequa() {}
-static short tgrea() {}
-static short tatsg() {}
-static short tperc() {}
-static short texcl() {}
-static short tplus() {}
-static short tminu() {}
-static short torrr() {}
-static short tampe() {}
-static short tpowe() {}
-static short tdivi() {}
static short tzero() {}
static short tpoin() {}
static short tnumb() {}
-static short tiden() {}
+
+static short tiden() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ else
+ return TK_IDENTIFIER;
+}
+
static short tchrL() {}
-static short tchra() {}
-static short tchrb() {}
-static short tchrc() {}
-static short tchrd() {}
-static short tchre() {}
-static short tchrf() {}
-static short tchrg() {}
-static short tchri() {}
-static short tchrl() {}
-static short tchrm() {}
-static short tchrn() {}
-static short tchro() {}
-static short tchrp() {}
-static short tchrr() {}
-static short tchrs() {}
-static short tchrt() {}
-static short tchru() {}
-static short tchrv() {}
-static short tchrw() {}
-static short tchrx() {}
-static short tchr_() {}
-static short token() {}
-static short tdoll() {}
-static short tisid() {}
-static short tnull() {}
-static short t0x1a() {}
-
-static short (*cprep_tokenize[256])() = {
- &tnull, &tille, &tille, &tille, &tisid, &tisid, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tcret, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &t0x1a, &tille, &tille, &tille, &tille, &tille,
- &tille, &texcl, &tquot, &thash, &tdoll, &tperc, &tampe, &tapos,
- &token, &token, &tmult, &tplus, &token, &tminu, &tpoin, &tdivi,
- &tzero, &tnumb, &tnumb, &tnumb, &tnumb, &tnumb, &tnumb, &tnumb,
- &tnumb, &tnumb, &tcolo, &token, &tless, &tequa, &tgrea, &token,
- &tatsg, &tiden, &tiden, &tiden, &tiden, &tiden, &tiden, &tiden,
- &tiden, &tiden, &tiden, &tiden, &tchrL, &tiden, &tchrn, &tiden,
- &tchrp, &tiden, &tiden, &tiden, &tiden, &tiden, &tiden, &tiden,
- &tchrx, &tiden, &tiden, &token, &token, &token, &tpowe, &tchr_,
- &token, &tchra, &tchrb, &tchrc, &tchrd, &tchre, &tchrf, &tchrg,
- &tiden, &tchri, &tiden, &tiden, &tchrl, &tchrm, &tchrn, &tchro,
- &tchrp, &tiden, &tchrr, &tchrs, &tchrt, &tchru, &tchrv, &tchrw,
- &tchrx, &tiden, &tiden, &token, &torrr, &token, &token, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille,
- &tille, &tille, &tille, &tille, &tille, &tille, &tille, &tille
+
+static short tchra() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("auto", tkidentifier->name))
+ return TK_AUTO;
+ if ((copts.cplusplus || !copts.only_std_keywords) && !strcmp("asm", tkidentifier->name))
+ return TK_ASM;
+ if (copts.cplusplus && !in_assembler && !preprocessing_only) {
+ if (!strcmp("and", tkidentifier->name))
+ return TK_LOGICAL_AND;
+ if (!strcmp("and_eq", tkidentifier->name))
+ return TK_AND_ASSIGN;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrb() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("break", tkidentifier->name))
+ return TK_BREAK;
+ if (copts.cplusplus) {
+ if (copts.booltruefalse && !strcmp("bool", tkidentifier->name))
+ return TK_BOOL;
+ if (!in_assembler && !preprocessing_only) {
+ if (!strcmp("bitand", tkidentifier->name))
+ return '&';
+ if (!strcmp("bitor", tkidentifier->name))
+ return '|';
+ }
+ }
+ if (copts.objective_c) {
+ if (!strcmp("bycopy", tkidentifier->name))
+ return TK_BYCOPY;
+ if (!strcmp("byref", tkidentifier->name))
+ return TK_BYREF;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrc() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("case", tkidentifier->name))
+ return TK_CASE;
+ if (!strcmp("char", tkidentifier->name))
+ return TK_CHAR;
+ if (!strcmp("const", tkidentifier->name))
+ return TK_CONST;
+ if (!strcmp("continue", tkidentifier->name))
+ return TK_CONTINUE;
+ if (copts.cplusplus) {
+ if (!strcmp("const_cast", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_CONST_CAST;
+ }
+ if (!strcmp("catch", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_CATCH;
+ }
+ if (!strcmp("class", tkidentifier->name))
+ return TK_CLASS;
+ if (!in_assembler && !preprocessing_only) {
+ if (!strcmp("compl", tkidentifier->name))
+ return '~';
+ }
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrd() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("default", tkidentifier->name))
+ return TK_DEFAULT;
+ if (!strcmp("do", tkidentifier->name))
+ return TK_DO;
+ if (!strcmp("double", tkidentifier->name))
+ return TK_DOUBLE;
+ if (copts.cplusplus) {
+ if (!strcmp("delete", tkidentifier->name))
+ return TK_DELETE;
+ if (!strcmp("dynamic_cast", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_DYNAMIC_CAST;
+ }
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchre() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("else", tkidentifier->name))
+ return TK_ELSE;
+ if (!strcmp("enum", tkidentifier->name))
+ return TK_ENUM;
+ if (!strcmp("extern", tkidentifier->name))
+ return TK_EXTERN;
+ if (copts.cplusplus) {
+ if (!strcmp("explicit", tkidentifier->name))
+ return TK_EXPLICIT;
+ if (!strcmp("export", tkidentifier->name) && !copts.ecplusplus)
+ return TK_EXPORT;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrf() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("float", tkidentifier->name))
+ return TK_FLOAT;
+ if (!strcmp("for", tkidentifier->name))
+ return TK_FOR;
+ if (copts.cplusplus) {
+ if (!strcmp("friend", tkidentifier->name))
+ return TK_FRIEND;
+ if (copts.booltruefalse && !strcmp("false", tkidentifier->name))
+ return TK_FALSE;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrg() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("goto", tkidentifier->name))
+ return TK_GOTO;
+ return TK_IDENTIFIER;
+}
+
+static short tchri() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("if", tkidentifier->name))
+ return TK_IF;
+ if (!strcmp("int", tkidentifier->name))
+ return TK_INT;
+ if (copts.cplusplus || copts.c9x) {
+ if (!strcmp("inline", tkidentifier->name))
+ return TK_INLINE;
+ } else if (!copts.only_std_keywords) {
+ if (!strcmp("inline", tkidentifier->name))
+ return TK_INLINE;
+ }
+ if (copts.objective_c) {
+ if (!strcmp("in", tkidentifier->name))
+ return TK_IN;
+ if (!strcmp("inout", tkidentifier->name))
+ return TK_INOUT;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrl() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("long", tkidentifier->name))
+ return TK_LONG;
+ return TK_IDENTIFIER;
+}
+
+static short tchrm() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (copts.cplusplus && !strcmp("mutable", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_MUTABLE;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrn(short t) {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (copts.cplusplus && t == 'n') {
+ if (!strcmp("new", tkidentifier->name))
+ return TK_NEW;
+ if (!strcmp("namespace", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_NAMESPACE;
+ }
+ if (!in_assembler && !preprocessing_only) {
+ if (!strcmp("not", tkidentifier->name))
+ return '!';
+ if (!strcmp("not_eq", tkidentifier->name))
+ return TK_LOGICAL_NE;
+ }
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchro() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (copts.cplusplus) {
+ if (!strcmp("operator", tkidentifier->name))
+ return TK_OPERATOR;
+ if (!in_assembler && !preprocessing_only) {
+ if (!strcmp("or", tkidentifier->name))
+ return TK_LOGICAL_OR;
+ if (!strcmp("or_eq", tkidentifier->name))
+ return TK_OR_ASSIGN;
+ }
+ }
+ if (copts.objective_c) {
+ if (!strcmp("out", tkidentifier->name))
+ return TK_OUT;
+ if (!strcmp("oneway", tkidentifier->name))
+ return TK_ONEWAY;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrp(short t) {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!copts.only_std_keywords && !strcmp("pascal", tkidentifier->name))
+ return TK_PASCAL;
+ if (copts.cplusplus && t == 'p') {
+ if (!strcmp("private", tkidentifier->name))
+ return TK_PRIVATE;
+ if (!strcmp("protected", tkidentifier->name))
+ return TK_PROTECTED;
+ if (!strcmp("public", tkidentifier->name))
+ return TK_PUBLIC;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrr() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("register", tkidentifier->name))
+ return TK_REGISTER;
+ if (!strcmp("return", tkidentifier->name))
+ return TK_RETURN;
+ if (copts.cplusplus && !strcmp("reinterpret_cast", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_REINTERPRET_CAST;
+ }
+ if (copts.c9x && !strcmp("restrict", tkidentifier->name))
+ return TK_RESTRICT;
+ return TK_IDENTIFIER;
+}
+
+static short tchrs() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("short", tkidentifier->name))
+ return TK_SHORT;
+ if (!strcmp("signed", tkidentifier->name))
+ return TK_SIGNED;
+ if (!strcmp("sizeof", tkidentifier->name))
+ return TK_SIZEOF;
+ if (!strcmp("static", tkidentifier->name))
+ return TK_STATIC;
+ if (!strcmp("struct", tkidentifier->name))
+ return TK_STRUCT;
+ if (!strcmp("switch", tkidentifier->name))
+ return TK_SWITCH;
+ if (copts.cplusplus && !strcmp("static_cast", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_STATIC_CAST;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrt() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("typedef", tkidentifier->name))
+ return TK_TYPEDEF;
+ if (copts.gcc_extensions && !strcmp("typeof", tkidentifier->name))
+ return TK_UU_TYPEOF_UU;
+ if (copts.cplusplus) {
+ if (!strcmp("this", tkidentifier->name))
+ return TK_THIS;
+ if (copts.booltruefalse && !strcmp("true", tkidentifier->name))
+ return TK_TRUE;
+ if (!strcmp("template", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_TEMPLATE;
+ }
+ if (!strcmp("try", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_TRY;
+ }
+ if (!strcmp("throw", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_THROW;
+ }
+ if (!strcmp("typeid", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_TYPEID;
+ }
+ if (!strcmp("typename", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_TYPENAME;
+ }
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchru() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("union", tkidentifier->name))
+ return TK_UNION;
+ if (!strcmp("unsigned", tkidentifier->name))
+ return TK_UNSIGNED;
+ if (copts.cplusplus && !strcmp("using", tkidentifier->name)) {
+ if (copts.ecplusplus)
+ CPrep_Warning(339);
+ return TK_USING;
+ }
+ return TK_IDENTIFIER;
+}
+
+static short tchrv() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("void", tkidentifier->name))
+ return TK_VOID;
+ if (!strcmp("volatile", tkidentifier->name))
+ return TK_VOLATILE;
+ if (copts.cplusplus && !strcmp("virtual", tkidentifier->name))
+ return TK_VIRTUAL;
+ return TK_IDENTIFIER;
+}
+
+static short tchrw() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+ if (!strcmp("while", tkidentifier->name))
+ return TK_WHILE;
+ if (copts.cplusplus && copts.wchar_type && !strcmp("wchar_t", tkidentifier->name))
+ return TK_WCHAR_T;
+ return TK_IDENTIFIER;
+}
+
+static short tchrx(short t) {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+
+ if (copts.cplusplus && t == 'x' && !in_assembler && !preprocessing_only) {
+ if (!strcmp("xor", tkidentifier->name))
+ return '^';
+ if (!strcmp("xor_eq", tkidentifier->name))
+ return TK_XOR_ASSIGN;
+ }
+
+ return TK_IDENTIFIER;
+}
+
+static short tchr_() {
+ at_linestart = 0;
+ pos = ReadIdentifier(pos - 1);
+ if (macrocheck && macrotest())
+ return 0;
+
+ if (!strcmp("__stdcall", tkidentifier->name))
+ return TK_UU_STDCALL;
+ if (!strcmp("__cdecl", tkidentifier->name))
+ return TK_UU_CDECL;
+ if (!strcmp("__fastcall", tkidentifier->name))
+ return TK_UU_FASTCALL;
+ if (!strcmp("__declspec", tkidentifier->name))
+ return TK_UU_DECLSPEC;
+ if (!strcmp("__asm", tkidentifier->name))
+ return TK_ASM;
+ if (!strcmp("__asm__", tkidentifier->name))
+ return TK_ASM;
+ if (!strcmp("__inline", tkidentifier->name))
+ return TK_INLINE;
+ if (!strcmp("__inline__", tkidentifier->name))
+ return TK_INLINE;
+ if (!strcmp("__restrict", tkidentifier->name))
+ return TK_RESTRICT;
+ if (!strcmp("__restrict__", tkidentifier->name))
+ return TK_RESTRICT;
+ if (!strcmp("__attribute__", tkidentifier->name))
+ return TK_UU_ATTRIBUTE_UU;
+ if (!strcmp("__far", tkidentifier->name))
+ return TK_UU_FAR;
+ if (!strcmp("__alignof__", tkidentifier->name))
+ return TK_UU_ALIGNOF_UU;
+ if (!strcmp("__typeof__", tkidentifier->name))
+ return TK_UU_TYPEOF_UU;
+ if (copts.c9x) {
+ if (!strcmp("_Bool", tkidentifier->name))
+ return TK_BOOL;
+ if (!strcmp("_Complex", tkidentifier->name))
+ return TK_U_COMPLEX;
+ if (!strcmp("_Imaginary", tkidentifier->name))
+ return TK_U_IMAGINARY;
+ }
+ if (copts.altivec_model && !strcmp("__vector", tkidentifier->name))
+ return TK_UU_VECTOR;
+ return TK_IDENTIFIER;
+}
+
+static short token(short t) {
+ at_linestart = 0;
+ return t;
+}
+
+static short tdoll(short t) {
+ at_linestart = 0;
+ return t;
+}
+
+static short tisid() {
+ if (!tokenstacklevel)
+ CError_Error(105);
+ return 0;
+}
+
+static short tnull(short t) {
+ if (tokenstacklevel > 0 || pos >= prep_file_end) {
+ at_linestart = 0;
+ return t;
+ } else {
+ pos[-1] = -64;
+ return TK_NEG6;
+ }
+}
+
+static short t0x1a() {
+ if (*pos == 0)
+ return 0;
+ else
+ return TK_NEG6;
+}
+
+typedef short (*TokenizePtr)(short);
+#define F(func) ((TokenizePtr) (&func))
+
+static TokenizePtr cprep_tokenize[256] = {
+ F(tnull), F(tille), F(tille), F(tille), F(tisid), F(tisid), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tcret), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(t0x1a), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(texcl), F(tquot), F(thash), F(tdoll), F(tperc), F(tampe), F(tapos),
+ F(token), F(token), F(tmult), F(tplus), F(token), F(tminu), F(tpoin), F(tdivi),
+ F(tzero), F(tnumb), F(tnumb), F(tnumb), F(tnumb), F(tnumb), F(tnumb), F(tnumb),
+ F(tnumb), F(tnumb), F(tcolo), F(token), F(tless), F(tequa), F(tgrea), F(token),
+ F(tatsg), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden),
+ F(tiden), F(tiden), F(tiden), F(tiden), F(tchrL), F(tiden), F(tchrn), F(tiden),
+ F(tchrp), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden),
+ F(tchrx), F(tiden), F(tiden), F(token), F(token), F(token), F(tpowe), F(tchr_),
+ F(token), F(tchra), F(tchrb), F(tchrc), F(tchrd), F(tchre), F(tchrf), F(tchrg),
+ F(tiden), F(tchri), F(tiden), F(tiden), F(tchrl), F(tchrm), F(tchrn), F(tchro),
+ F(tchrp), F(tiden), F(tchrr), F(tchrs), F(tchrt), F(tchru), F(tchrv), F(tchrw),
+ F(tchrx), F(tiden), F(tiden), F(token), F(torrr), F(token), F(token), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
+ F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille)
};
short lookahead() {
+ SInt32 state;
+ short t;
+
+ CPrep_TokenStreamGetState(&state);
+ t = lex();
+ CPrep_TokenStreamSetState(&state);
+
+ return t;
}
short lookahead_noeol() {
+ SInt32 state;
+ short t;
+
+ CPrep_TokenStreamGetState(&state);
+ do {
+ t = lex();
+ } while (t == TK_NEG7);
+ CPrep_TokenStreamSetState(&state);
+
+ return t;
}
static void CPrep_StringConCat(Boolean flag) {
@@ -160,7 +1893,45 @@ short lex() {
}
short plex() {
+ // does not match - global refs in wrong order
+ short t;
+
+ while (1) {
+ t = prepskipnextchar();
+ pos = nextcharpos;
+ if ((t = cprep_tokenize[t](t)))
+ return t;
+
+ if (!*pos) {
+ if (tokenstacklevel > 0) {
+ poptokenseq();
+ } else if (filesp > 0) {
+ popfile();
+ } else {
+ break;
+ }
+ }
+ }
+
+ return 0;
}
short lexidentifier() {
+ short t;
+ char *save_pos;
+
+ t = prepskipnextchar();
+ pos = nextcharpos;
+ at_linestart = 0;
+ if ((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z') || (t == '_')) {
+ pos = ReadIdentifier(pos - 1);
+ return TK_IDENTIFIER;
+ } else if (t == '.') {
+ save_pos = pos;
+ if (prepnextchar() == '.' && prepnextchar() == '.')
+ return TK_ELLIPSIS;
+ else
+ pos = save_pos;
+ }
+ return t;
}
diff --git a/compiler_and_linker/FrontEnd/C/CScope.c b/compiler_and_linker/FrontEnd/C/CScope.c
index 7423c07..06cbd6c 100644
--- a/compiler_and_linker/FrontEnd/C/CScope.c
+++ b/compiler_and_linker/FrontEnd/C/CScope.c
@@ -1,5 +1,9 @@
#include "compiler.h"
#include "compiler/CError.h"
+#include "compiler/CMangler.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CScope.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
@@ -1016,7 +1020,7 @@ static NameSpaceObjectList *CScope_FindLookupName(NameSpaceLookupList *list, Has
if (r6->object->otype == r30->object->otype) {
switch (r6->object->otype) {
case OT_TYPE:
- if ((OBJ_TYPE(r6->object)->type == OBJ_TYPE(r30->object)->type) && (OBJ_TYPE(r6->object)->unk6 == OBJ_TYPE(r30->object)->unk6))
+ if ((OBJ_TYPE(r6->object)->type == OBJ_TYPE(r30->object)->type) && (OBJ_TYPE(r6->object)->qual == OBJ_TYPE(r30->object)->qual))
goto break1;
break;
case OT_TYPETAG:
@@ -1196,7 +1200,7 @@ static Boolean CScope_SetupParseNameResult(CScopeParseResult *result, NameSpaceO
return 0;
case OT_TYPE:
result->x8 = OBJ_TYPE(list->object)->type;
- result->xC = OBJ_TYPE(list->object)->unk6;
+ result->xC = OBJ_TYPE(list->object)->qual;
result->obj_10 = list->object;
result->name_4 = name;
result->x20 = 1;
@@ -1388,7 +1392,7 @@ inline Boolean CScope_NSIteratorNext(CScopeNSIterator *iterator) {
}
}
-Type *CScope_GetType(NameSpace *nspace, HashNameNode *name, void **unk6) {
+Type *CScope_GetType(NameSpace *nspace, HashNameNode *name, UInt32 *qual) {
CScopeParseResult result;
CScopeNSIterator iterator;
NameSpaceObjectList *list;
@@ -1400,13 +1404,13 @@ Type *CScope_GetType(NameSpace *nspace, HashNameNode *name, void **unk6) {
do {
for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) {
if (list->object->otype == OT_TYPETAG) {
- if (unk6)
- *unk6 = NULL;
+ if (qual)
+ *qual = 0;
return OBJ_TYPE_TAG(list->object)->type;
}
if (list->object->otype == OT_TYPE) {
- if (unk6)
- *unk6 = OBJ_TYPE(list->object)->unk6;
+ if (qual)
+ *qual = OBJ_TYPE(list->object)->qual;
return OBJ_TYPE(list->object)->type;
}
}
@@ -2429,7 +2433,7 @@ static void CScope_AddUsingObject(BClassList *bcl, NameSpace *nspace, ObjBase *o
if (!nspace->theclass) {
if ((list = CScope_FindQualName(nspace, name)) && (list->object->otype == OT_TYPE) &&
(OBJ_TYPE(obj)->type == OBJ_TYPE(list->object)->type) &&
- (OBJ_TYPE(obj)->unk6 == OBJ_TYPE(list->object)->unk6))
+ (OBJ_TYPE(obj)->qual == OBJ_TYPE(list->object)->qual))
return;
}
copy = galloc(sizeof(ObjType));
@@ -2530,7 +2534,7 @@ void CScope_AddClassUsingDeclaration(TypeClass *tclass, TypeClass *tclass2, Hash
}
}
-void CScope_ParseUsingDeclaration(NameSpace *nspace, AccessType access) {
+void CScope_ParseUsingDeclaration(NameSpace *nspace, short access, Boolean flag) {
// almost matches, slight bit of register weirdness
CScopeParseResult result;
diff --git a/compiler_and_linker/unsorted/CABI.c b/compiler_and_linker/unsorted/CABI.c
new file mode 100644
index 0000000..0b29b9d
--- /dev/null
+++ b/compiler_and_linker/unsorted/CABI.c
@@ -0,0 +1,93 @@
+#include "compiler/CABI.h"
+#include "compiler/CMachine.h"
+#include "compiler/types.h"
+#include "compiler/CompilerTools.h"
+
+static void *trans_vtboffsets; // TODO type
+static void *cabi_pathroot; // TODO type - 8 byte struct??
+static void *cabi_pathcur; // TODO type
+static TypeClass *cabi_loop_class;
+static Boolean cabi_loop_construct;
+
+short CABI_GetStructResultArgumentIndex(void) {
+ return 0;
+}
+
+Type *CABI_GetSizeTType(void) {
+ return (Type *) &stunsignedlong;
+}
+
+Type *CABI_GetPtrDiffTType(void) {
+ return (Type *) &stsignedlong;
+}
+
+SInt16 CABI_StructSizeAlignValue(Type *type, SInt32 size) {}
+
+void CABI_ReverseBitField(TypeBitfield *tbitfield) {}
+
+// not sure about the sig for this, it's unused lmao
+static void CABI_AllocateZeroVTablePointer() {}
+
+static SInt32 CABI_GetBaseSize(TypeClass *tclass) {}
+static void CABI_AllocateBases() {}
+static void CABI_AllocateVirtualBasePointers() {}
+static void CABI_GetMemberOffset() {}
+static void CABI_AllocateMembers() {}
+static void CABI_AllocateVirtualBases() {}
+static void CABI_FindZeroDeltaVPtr() {}
+static void CABI_FindZeroVirtualBaseMember() {}
+
+void CABI_AddVTable(TypeClass *tclass) {
+ tclass->vtable = galloc(sizeof(VTable));
+ memclrw(tclass->vtable, sizeof(VTable));
+}
+
+SInt32 CABI_GetVTableOffset(TypeClass *tclass) {
+ return 0;
+}
+
+static void CABI_GetBaseVTableSize() {}
+static void CABI_ApplyClassFlags() {}
+static void CABI_AllocateVTable() {}
+void CABI_LayoutClass(DeclE *decle, TypeClass *tclass) {}
+void CABI_MakeDefaultArgConstructor(Object *obj, TypeClass *tclass) {}
+static void CABI_ThisArg() {}
+ENode *CABI_MakeThisExpr(TypeClass *tclass, SInt32 offset) {}
+static void CABI_VArg() {}
+static void CABI_MakeVArgExpr() {}
+static void CABI_MakeCopyConArgExpr() {}
+static void CABI_InitVBasePtr1() {}
+static void CABI_InitVBasePtrs() {}
+static void CABI_GetVBasePath() {}
+static void CABI_GetVBasePtr() {}
+static SInt32 CABI_FindNVBase(TypeClass *tclass, TypeClass *base, SInt32 offset) {}
+SInt32 CABI_GetCtorOffsetOffset(TypeClass *tclass, TypeClass *base) {}
+static void CABI_InitVBaseCtorOffsets() {}
+static void CABI_InitVTablePtrs() {}
+static Boolean CABI_IsOperatorNew(Object *obj) {}
+Object *CABI_ConstructorCallsNew(TypeClass *tclass) {}
+void CABI_TransConstructor(Object *obj, Statement *stmt, TypeClass *tclass, TransConstructorCallback callback, Boolean flag) {}
+void CABI_MakeDefaultConstructor(TypeClass *tclass, Object *obj) {}
+static void CABI_AssignObject() {}
+static void CABI_FindIntegralSizeType() {}
+static void CABI_AppendCopyRegion() {}
+static void CABI_ClassInitLoopCallBack() {}
+static void CABI_CopyConAssignCB() {}
+void CABI_MakeDefaultCopyConstructor(TypeClass *tclass, Object *obj) {}
+void CABI_MakeDefaultAssignmentOperator(TypeClass *tclass, Object *obj) {}
+static void CABI_DestroyMembers() {}
+static void CABI_DestroyBases() {}
+static void CABI_DestroyVBases() {}
+void CABI_TransDestructor(Object *obj1, Object *obj2, Statement *stmt, TypeClass *tclass) {}
+void CABI_MakeDefaultDestructor(TypeClass *tclass, Object *obj) {}
+static void CABI_CreateLayeredDestructor() {}
+void CABI_MakeLayeredDestructor(TypeClass *tclass, Object *obj) {}
+
+Object *CABI_GetDestructorObject(Object *obj, int what) {
+ return obj;
+}
+
+static void CABI_AddLayeredDestructor() {}
+void CABI_AddLayeredDestructors(TypeClass *tclass) {}
+
+ENode *CABI_DestroyObject(Object *dtor, ENode *objexpr, UInt8 mode, Boolean flag1, Boolean flag2) {}
diff --git a/compiler_and_linker/unsorted/CClass.c b/compiler_and_linker/unsorted/CClass.c
new file mode 100644
index 0000000..7932586
--- /dev/null
+++ b/compiler_and_linker/unsorted/CClass.c
@@ -0,0 +1,122 @@
+#include "compiler/CClass.h"
+
+typedef struct OVClassBase {
+ struct OVClassBase *next;
+ struct OVClass *ovclass;
+ Boolean is_virtual;
+} OVClassBase;
+
+typedef struct OVFunc {
+ struct OVFunc *next;
+ Object *obj;
+ struct OVClass *ovc8;
+ struct OVFunc *ovfC;
+ struct OVFunc *ovf10;
+} OVFunc;
+
+typedef struct OVClass {
+ TypeClass *tclass;
+ OVFunc *vfuncs;
+ OVClassBase *bases;
+ SInt32 offset;
+ SInt32 voffset;
+ Boolean alloced_vtable;
+} OVClass;
+
+static TypeClass *main_class;
+static void *cclass_thunklist; // TODO type
+static TypeClass *cclass_isbase_mostderived;
+static void *cclass_isbase_foundoffset; // TODO type
+static Boolean cclass_isambigbase;
+static short cclass_founddepth;
+static void *vtable_object_data; // TODO type
+static void *vtable_data_size; // TODO type
+static VTableObjectLink *vtable_object_links;
+static TypeClass *cclass_vbase;
+static OVClass *cclass_ovbase;
+static OVClass *cclass_root;
+static Object *found_pure;
+static Boolean check_pures;
+static Object *cclass_dominator_vobject;
+static SInt32 cclass_dominator_voffset;
+static Object *cclass_dominator_oobject;
+static TypeClass *cclass_dominator_oclass;
+static SInt32 cclass_dominator_ooffset;
+static Object *cclass_dominator_eobject;
+
+void CClass_Init(void) {}
+void CClass_GenThunks(void) {}
+static Object *CClass_ThunkObject(Object *obj, SInt32 a, SInt32 b, SInt32 c) {}
+static Boolean CClass_IsZeroOffsetClass(TypeClass *a, TypeClass *b) {}
+static UInt8 CClass_IsCovariantResult(Type *a, UInt32 qualA, Type *b, UInt32 qualB) {}
+UInt8 CClass_GetOverrideKind(TypeFunc *a, TypeFunc *b, Boolean errorflag) {}
+Boolean CClass_IsEmpty(TypeClass *tclass) {}
+Boolean CClass_IsNonStaticMemberFunc(TypeMethod *tmethod) {}
+Object *CClass_DefaultConstructor(TypeClass *tclass) {}
+Object *CClass_DummyDefaultConstructor(TypeClass *tclass) {}
+ENode *CClass_DefaultConstructorCall(TypeClass *a, TypeClass *b, ENode *expr, SInt32 unkshortparam, Boolean flag1, Boolean flag2, Boolean *errorflag) {}
+Object *CClass_AssignmentOperator(TypeClass *tclass) {}
+Object *CClass_CopyConstructor(TypeClass *tclass) {}
+NameSpaceObjectList *CClass_MemberObject(TypeClass *tclass, HashNameNode *name) {}
+Object *CClass_Constructor(TypeClass *tclass) {}
+Object *CClass_Destructor(TypeClass *tclass) {}
+Boolean CClass_IsConstructor(Object *obj) {}
+Boolean CClass_IsDestructor(Object *obj) {}
+Boolean CClass_IsPODClass(TypeClass *tclass) {}
+Boolean CClass_IsTrivialCopyClass(TypeClass *tclass) {}
+Boolean CClass_IsTrivialCopyAssignClass(TypeClass *tclass) {}
+Boolean CClass_ReferenceArgument(TypeClass *tclass) {}
+BClassList *CClass_GetPathCopy(BClassList *path, Boolean is_global) {}
+BClassList *CClass_AppendPath(BClassList *a, BClassList *b) {}
+static AccessType CClass_GetPathAccess(BClassList *path) {}
+Boolean CClass_IsMoreAccessiblePath(BClassList *path1, BClassList *path2) {}
+static BClassList *CClass_GetBasePathRec(TypeClass *a, TypeClass *b, SInt32 offset, short depth) {}
+BClassList *CClass_GetBasePath(TypeClass *a, TypeClass *b, short *founddepth, Boolean *isambigbase) {}
+Boolean CClass_IsBaseClass(TypeClass *a, TypeClass *b, short *founddepth, Boolean pathcheckflag, Boolean ambigerrorflag) {}
+TypeClass *CClass_GetQualifiedClass(void) {}
+ENode *CClass_AccessPathCast(BClassList *path, ENode *expr, Boolean flag) {}
+ENode *CClass_ClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean ambigerrorflag, Boolean pathcheckflag) {}
+ENode *CClass_DirectBasePointerCast(ENode *expr, TypeClass *a, TypeClass *b) {}
+SInt32 CClass_GetPathOffset(BClassList *path) {}
+Boolean CClass_ClassDominates(TypeClass *a, TypeClass *b) {}
+SInt32 CClass_VirtualBaseOffset(TypeClass *a, TypeClass *b) {}
+SInt32 CClass_VirtualBaseVTableOffset(TypeClass *a, TypeClass *b) {}
+SInt32 CClass_GetMemberOffset(TypeClass *tclass, HashNameNode *name, ObjMemberVar **obj) {}
+Boolean CClass_OverridesBaseMember(TypeClass *tclass, HashNameNode *name, Object *obj) {}
+static OVClass *CClass_FindOVClass(OVClass *ovclass, TypeClass *tclass, SInt32 offset) {}
+static OVClass *CClass_BuildOVClassTree(OVClass *root, TypeClass *tclass, SInt32 offset, SInt32 voffset) {}
+static Boolean CClass_IsBaseOf(OVClass *a, OVClass *b) {}
+static void CClass_FindOVFunc(OVClass *a, OVClass *b, OVFunc *func) {}
+static TypeList *CClass_GetCoVariantClassList(TypeList *list, TypeClass *tclass, Object *func, Boolean flag) {}
+static TypeMethod *CClass_GetCovariantType(TypeMethod *tmethod, Type *type) {}
+static Object *CClass_FindCovariantFunction(Object *func, Type *type) {}
+static ObjectList *CClass_DeclareCovariantFuncs(ObjectList *list, Object *func, TypeClass *tclass) {}
+void CClass_DefineCovariantFuncs(Object *method, CI_FuncData *ifuncdata) {}
+static void CClass_OverrideOVClassTree(OVClass *ovclass) {}
+static void CClass_AllocVTableRec(OVClass *ovclass) {}
+static Object *CClass_CheckClass(OVClass *ovclass, Boolean errorflag) {}
+static void CClass_AllocVTable(TypeClass *tclass) {}
+static Object *CClass_CheckVirtuals(TypeClass *tclass) {}
+static void CClass_CheckVirtualBaseOverrides(OVClass *a, OVClass *b, Boolean flag) {}
+static void CClass_CheckHideVirtual(OVClass *a, OVClass *b) {}
+void CClass_CheckOverrides(TypeClass *tclass) {}
+static void CClass_FindDominator(TypeClass *tclass1, SInt32 offset1, Object *object1, TypeClass *tclass2, SInt32 offset2, TypeClass *base) {}
+static void CClass_ConstructVTable(TypeClass *tclass, SInt32 voffset, SInt32 offset, TypeClass *base) {}
+void CClass_ClassDefaultFuncAction(TypeClass *tclass) {}
+void CClass_ClassAction(TypeClass *tclass) {}
+void CClass_MakeStaticActionClass(TypeClass *tclass) {}
+Object *CClass_CheckPures(TypeClass *tclass) {}
+void CClass_MemberDef(Object *obj, TypeClass *tclass) {}
+Object *CClass_ThisSelfObject(void) {}
+ENode *CClass_CreateThisSelfExpr(void) {}
+static Boolean CClass_BaseMemberAccess(BClassList *path, AccessType access) {}
+static Boolean CClass_CanAccess(BClassList *path, AccessType access) {}
+void CClass_CheckPathAccess(BClassList *path, Object *obj, AccessType access) {}
+static BClassList *CClass_PathCleanup(BClassList *path, TypeClass *tclass) {}
+void CClass_CheckStaticAccess(BClassList *path, TypeClass *tclass, AccessType access) {}
+void CClass_CheckObjectAccess(BClassList *path, Object *obj) {}
+void CClass_CheckEnumAccess(BClassList *path, ObjEnumConst *objec) {}
+static Type *CClass_PointerTypeCopy(Type *type) {}
+Type *CClass_CombineClassAccessQualifiers(Type *type, UInt32 qual1, UInt32 qual2, UInt32 *outflags) {}
+static void CClass_OptimizeBitFieldAccess(Type **type, SInt32 *offset) {}
+ENode *CClass_AccessMember(ENode *classexpr, Type *type, UInt32 qual, SInt32 offset) {}
diff --git a/compiler_and_linker/unsorted/CCompiler.c b/compiler_and_linker/unsorted/CCompiler.c
index d496389..8339cf6 100644
--- a/compiler_and_linker/unsorted/CCompiler.c
+++ b/compiler_and_linker/unsorted/CCompiler.c
@@ -3,6 +3,7 @@
#include "compiler/types.h"
#include "pref_structs.h"
#include "compiler/CompilerTools.h"
+#include "compiler/CPrep.h"
Boolean systemHandles;
@@ -11,14 +12,6 @@ Boolean crippled;
SInt32 license_cookie;
CParams cparams;
-// TODO move me to CParser.c, or maybe CMachine.c?
-Type sttemplexpr = {TYPETEMPLDEPEXPR, 0};
-Type stillegal = {TYPEILLEGAL, 1};
-Type stvoid = {TYPEVOID, 0};
-TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0};
-TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0};
-// TODO move me to CParser.c
-
static void get_extension(ConstStringPtr src, char *dst) {
int ep;
diff --git a/compiler_and_linker/unsorted/CDecl.c b/compiler_and_linker/unsorted/CDecl.c
new file mode 100644
index 0000000..d6665a6
--- /dev/null
+++ b/compiler_and_linker/unsorted/CDecl.c
@@ -0,0 +1,4902 @@
+#include "compiler/CDecl.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CError.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler/templates.h"
+#include "compiler/tokens.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/CMangler.h"
+#include "compiler/CClass.h"
+#include "compiler/CParser.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInit.h"
+#include "compiler/CInt64.h"
+#include "compiler/CExpr.h"
+#include "compiler/CMachine.h"
+#include "compiler/CInline.h"
+#include "compiler/CABI.h"
+
+// TODO MOVE ME
+extern void CExcept_ScanExceptionSpecification(TypeFunc *tfunc);
+extern void CExcept_CompareSpecifications(ExceptSpecList *a, ExceptSpecList *b);
+extern void CObjC_ParseDefs(TypeStruct *tstruct);
+extern void CTempl_Parse(TypeClass *tclass, short access);
+extern Boolean CTempl_InstantiateTemplateClass(TemplClass *cls);
+extern Boolean CTemplTool_IsTemplateArgumentDependentType(Type *type);
+extern TemplClass *CTemplTool_GetSelfRefTemplate(Type *type);
+extern Type *CTemplTool_ResolveMemberSelfRefs(TypeClass *tclass, Type *type, UInt32 *qual);
+extern Boolean CTempl_IsQualifiedMember(DeclInfo *declinfo, Type *type, NameSpace **nspace);
+extern Object *CTempl_TemplateFunctionCheck(DeclInfo *declinfo, NameSpaceObjectList *list);
+extern TemplArg *CTempl_ParseUncheckTemplArgs(void *a, Boolean flag);
+extern TemplArg *CTemplTool_MakeGlobalTemplArgCopy(TemplArg *args);
+extern void CTemplClass_RegisterFriend(TemplClass *tmclass, DeclInfo *declinfo);
+extern void CTemplClass_RegisterBaseClass(TemplClass *tmclass, Type *baseclass, short access, Boolean is_virtual);
+extern void CTemplClass_RegisterObjectDef(TemplClass *tmclass, ObjBase *obj);
+extern void CTemplClass_RegisterObjectInit(TemplClass *tmclass, ObjBase *obj, ENode *expr);
+extern void CTemplClass_DefineMember(TemplClass *tmclass, Object *obj, FileOffsetInfo *fileoffset, TStream *stream);
+extern void CTemplClass_CompleteClass(TemplClass *tmclass, DeclE *decle);
+extern void CTemplClass_RegisterEnumType(TemplClass *tmclass, TypeEnum *tenum);
+extern void CTemplClass_RegisterEnumerator(TemplClass *tmclass, ObjEnumConst *oec, ENode *expr);
+extern TypeClass *CTemplClass_DefineNestedClass(TemplClass *tmclass, HashNameNode *name, short mode);
+extern void CSOM_FixNewDeleteFunctype(TypeFunc *tfunc);
+extern void CSOM_CheckFuncType(TypeFunc *tfunc);
+extern void CSOM_ClassComplete(TypeClass *tclass);
+extern void CSOM_MakeSOMClass(TypeClass *tclass);
+typedef struct BrowseStruct {
+ void *x0;
+ void *x4;
+ void *x8;
+ void *xC;
+} BrowseStruct;
+extern void CBrowse_BeginStruct(DeclInfo *declinfo, TypeStruct *type, BrowseStruct *bs);
+extern void CBrowse_EndStruct(SInt32 offset, BrowseStruct *bs);
+extern void CBrowse_AddStructMember(StructMember *member, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_BeginClass(DeclInfo *declinfo, BrowseStruct *bs);
+extern void CBrowse_EndClass(SInt32 offset, BrowseStruct *bs);
+extern void CBrowse_NewTypedef(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file, SInt32 tokenline, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_NewData(Object *obj, CPrepFileInfo *file, SInt32 tokenline, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_NewFunction(Object *obj, CPrepFileInfo *file, CPrepFileInfo *file2, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_NewEnum(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file, CPrepFileInfo *file2, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_NewEnumConstant(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file, CPrepFileInfo *file2, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_AddClassMemberData(Object *obj, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_AddClassMemberFunction(Object *obj, SInt32 tokenoffset, SInt32 fileoffset);
+extern void CBrowse_AddClassMemberVar(ObjMemberVar *obj, SInt32 tokenoffset, SInt32 fileoffset);
+
+AccessType global_access;
+FileOffsetInfo member_fileoffset;
+
+// forward declarations
+static void scandirectdecl1(DeclInfo *declinfo);
+
+Type *CDecl_NewStructType(SInt32 size, SInt16 align) {
+ TypeStruct *tstruct = galloc(sizeof(TypeStruct));
+ memclrw(tstruct, sizeof(TypeStruct));
+
+ tstruct->type = TYPESTRUCT;
+ tstruct->size = size;
+ tstruct->align = align;
+ tstruct->stype = STRUCT_TYPE_STRUCT;
+
+ return (Type *) tstruct;
+}
+
+Type *CDecl_NewArrayType(Type *type, SInt32 size) {
+ TypePointer *tarray = galloc(sizeof(TypePointer));
+ memclrw(tarray, sizeof(TypePointer));
+
+ tarray->type = TYPEARRAY;
+ tarray->size = size;
+ tarray->target = type;
+ tarray->qual = 0;
+
+ return (Type *) tarray;
+}
+
+Type *CDecl_NewPointerType(Type *type) {
+ TypePointer *tptr = galloc(sizeof(TypePointer));
+ memclrw(tptr, sizeof(TypePointer));
+
+ tptr->type = TYPEPOINTER;
+ tptr->size = 4;
+ tptr->target = type;
+
+ return (Type *) tptr;
+}
+
+Type *CDecl_NewRefPointerType(Type *type) {
+ TypePointer *tptr = galloc(sizeof(TypePointer));
+ memclrw(tptr, sizeof(TypePointer));
+
+ tptr->type = TYPEPOINTER;
+ tptr->size = 4;
+ tptr->target = type;
+ tptr->qual = Q_REFERENCE;
+
+ return (Type *) tptr;
+}
+
+Type *CDecl_NewTemplDepType(TypeTemplDepType tdt) {
+ TypeTemplDep *t = galloc(sizeof(TypeTemplDep));
+ memclrw(t, sizeof(TypeTemplDep));
+
+ t->type = TYPETEMPLATE;
+ t->size = 1;
+ t->dtype = tdt;
+
+ return (Type *) t;
+}
+
+void CDecl_SetResultReg(TypeFunc *tfunc) {
+}
+
+static void CDecl_SetFuncResultReg(TypeFunc *tfunc) {
+}
+
+void CDecl_SetFuncFlags(TypeFunc *tfunc, UInt32 flags) {
+ CDecl_SetResultReg(tfunc);
+}
+
+static void CDecl_ParseCPPFuncDecl(TypeFunc *tfunc) {
+ for (;;) {
+ if (tk == TK_CONST) {
+ if (tfunc->flags & FUNC_FLAGS_CONST)
+ CError_Warning(313, "const");
+ tfunc->flags |= FUNC_FLAGS_CONST;
+ tk = lex();
+ } else if (tk == TK_VOLATILE) {
+ if (tfunc->flags & FUNC_FLAGS_VOLATILE)
+ CError_Warning(313, "volatile");
+ tfunc->flags |= FUNC_FLAGS_VOLATILE;
+ tk = lex();
+ } else {
+ break;
+ }
+ }
+
+ if (tk == TK_THROW)
+ CExcept_ScanExceptionSpecification(tfunc);
+}
+
+void CDecl_NewConvFuncType(DeclInfo *declinfo) {
+ TypeFunc *tfunc;
+
+ if (tk != '(')
+ CError_Error(114);
+ else
+ tk = lex();
+
+ if (tk == TK_VOID)
+ tk = lex();
+
+ if (tk != ')')
+ CError_Error(115);
+ else
+ tk = lex();
+
+ tfunc = galloc(sizeof(TypeFunc));
+ memclrw(tfunc, sizeof(TypeFunc));
+ declinfo->name = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual);
+ tfunc->type = TYPEFUNC;
+ tfunc->functype = declinfo->thetype;
+ tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE);
+ tfunc->flags = FUNC_FLAGS_40;
+ declinfo->x49 = 0;
+ CDecl_SetFuncFlags(tfunc, 1);
+ CDecl_ParseCPPFuncDecl(tfunc);
+
+ declinfo->thetype = (Type *) tfunc;
+ declinfo->qual &= ~(Q_CONST | Q_VOLATILE);
+ declinfo->storageclass = 0;
+}
+
+void CDecl_CompleteType(Type *type) {
+ switch (type->type) {
+ case TYPEPOINTER:
+ if ((TYPE_POINTER(type)->qual & Q_REFERENCE) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) {
+ type = TYPE_POINTER(type)->target;
+ break;
+ }
+ return;
+ case TYPEARRAY:
+ do {
+ type = TYPE_POINTER(type)->target;
+ } while (IS_TYPE_ARRAY(type));
+ if (IS_TYPE_CLASS(type))
+ break;
+ return;
+ case TYPECLASS:
+ break;
+ default:
+ return;
+ }
+
+ if ((TYPE_CLASS(type)->flags & (CLASS_FLAGS_2 | CLASS_FLAGS_800)) == CLASS_FLAGS_800)
+ CTempl_InstantiateTemplateClass(TEMPL_CLASS(type));
+}
+
+Boolean IsCompleteType(Type *type) {
+ switch (type->type) {
+ case TYPEVOID:
+ CError_Error(126);
+ return 0;
+ case TYPEFUNC:
+ CError_Error(146);
+ return 0;
+ case TYPESTRUCT:
+ if (!type->size) {
+ CError_Error(136, type, 0);
+ return 0;
+ }
+ return 1;
+ case TYPECLASS:
+ if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_2) && (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_800) || !CTempl_InstantiateTemplateClass(
+ TEMPL_CLASS(type)))) {
+ CError_Error(136, type, 0);
+ return 0;
+ }
+ return 1;
+ default:
+ if (!type->size) {
+ CError_Error(145);
+ return 0;
+ }
+ return 1;
+ }
+}
+
+Boolean CanAllocObject(Type *type) {
+ switch (type->type) {
+ case TYPEVOID:
+ CError_Error(126);
+ return 0;
+ case TYPEFUNC:
+ CError_Error(146);
+ return 0;
+ case TYPECLASS:
+ if (TYPE_CLASS(type)->flags & CLASS_FLAGS_ABSTRACT) {
+ CError_AbstractClassError(TYPE_CLASS(type));
+ return 0;
+ }
+ default:
+ return 1;
+ }
+}
+
+Boolean CanCreateObject(Type *type) {
+ if (!CanAllocObject(type))
+ return 0;
+
+ if (IS_TYPE_CLASS(type)) {
+ if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) {
+ CError_Error(191);
+ return 0;
+ }
+ if (TYPE_CLASS(type)->objcinfo) {
+ CError_Error(307);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static Boolean CanCreateHandleMemberObject(Type *type) {
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+
+ if (!CanCreateObject(type))
+ return 0;
+
+ if (IS_TYPE_CLASS(type)) {
+ if (CClass_Destructor(TYPE_CLASS(type)) || CClass_Constructor(TYPE_CLASS(type))) {
+ CError_Error(191);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+void makethetypepointer(DeclInfo *declinfo, UInt32 qual) {
+ declinfo->thetype = CDecl_NewPointerType(declinfo->thetype);
+ TYPE_POINTER(declinfo->thetype)->qual = qual;
+}
+
+void CDecl_AddThisPointerArgument(TypeFunc *tfunc, TypeClass *tclass) {
+ Type *ptype;
+ FuncArg *arg;
+
+ ptype = CDecl_NewPointerType(!tclass->sominfo ? (Type *) tclass : &stvoid);
+ TYPE_POINTER(ptype)->qual = Q_CONST;
+
+ arg = CParser_NewFuncArg();
+ arg->name = this_name_node;
+ arg->type = ptype;
+ if (tfunc->flags & FUNC_FLAGS_CONST)
+ arg->qual |= Q_CONST;
+ if (tfunc->flags & FUNC_FLAGS_VOLATILE)
+ arg->qual |= Q_VOLATILE;
+ arg->next = tfunc->args;
+ tfunc->args = arg;
+}
+
+void CDecl_MakePTMFuncType(TypeFunc *tfunc) {
+ Type *cvoidp;
+ FuncArg *arg1;
+ FuncArg *arg2;
+
+ cvoidp = CDecl_NewPointerType(&stvoid);
+ TYPE_POINTER(cvoidp)->qual = Q_CONST;
+
+ arg1 = CParser_NewFuncArg();
+ arg1->name = this_name_node;
+ arg1->type = cvoidp;
+ if (tfunc->flags & FUNC_FLAGS_CONST)
+ arg1->qual |= Q_CONST;
+ if (tfunc->flags & FUNC_FLAGS_VOLATILE)
+ arg1->qual |= Q_VOLATILE;
+
+ arg2 = CParser_NewFuncArg();
+ arg2->name = this_name_node;
+ arg2->type = cvoidp;
+ arg2->qual = Q_CONST;
+
+ arg1->next = tfunc->args;
+ arg2->next = arg1;
+ tfunc->args = arg2;
+ tfunc->flags |= FUNC_FLAGS_80;
+}
+
+void CDecl_AddArgument(TypeFunc *tfunc, Type *argtype) {
+ FuncArg *arg = CParser_NewFuncArg();
+ arg->type = argtype;
+
+ arg->next = tfunc->args;
+ tfunc->args = arg;
+
+ if (arg->next && arg->next->type == &stvoid)
+ arg->next = NULL;
+}
+
+Boolean CDecl_CheckArrayIntegr(Type *type) {
+ if (!IsCompleteType(type))
+ return 0;
+
+ if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) {
+ CError_Error(289);
+ return 0;
+ }
+
+ if (IS_TYPE_REFERENCE(type)) {
+ CError_Error(196);
+ return 0;
+ }
+
+ return CanCreateObject(type);
+}
+
+static Boolean checkfuncintegr(Type *type) {
+ if (IS_TYPE_VOID(type))
+ return 1;
+
+ if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) {
+ CError_Error(283);
+ return 0;
+ }
+
+ return CanCreateObject(type);
+}
+
+void CDecl_ParseDirectFuncDecl(DeclInfo *declinfo) {
+ FuncArg *list;
+ TypeFunc *tfunc;
+
+ if (tk == ')') {
+ if (copts.cplusplus)
+ list = NULL;
+ else
+ list = &oldstyle;
+ tk = lex();
+ } else {
+ list = parameter_type_list(declinfo);
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+ }
+
+ tfunc = galloc(sizeof(TypeFunc));
+ memclrw(tfunc, sizeof(TypeFunc));
+ tfunc->type = TYPEFUNC;
+ tfunc->args = list;
+ if (declinfo->qual & Q_PASCAL) {
+ declinfo->qual &= ~Q_PASCAL;
+ tfunc->flags = FUNC_FLAGS_PASCAL;
+ }
+
+ if (copts.cplusplus) {
+ CDecl_ParseCPPFuncDecl(tfunc);
+ if (declinfo->storageclass == OBJECT_SCLASS_104 && tfunc->exspecs)
+ CError_Error(264);
+ }
+
+ scandirectdecl1(declinfo);
+ if (!checkfuncintegr(declinfo->thetype))
+ declinfo->thetype = &stvoid;
+
+ tfunc->functype = declinfo->thetype;
+ tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE);
+ declinfo->thetype = (Type *) tfunc;
+ declinfo->qual &= ~(Q_CONST | Q_VOLATILE);
+ declinfo->x49 = 0;
+}
+
+static void scandirectdecl1(DeclInfo *declinfo) {
+ Boolean flag;
+ CInt64 len;
+ ENode *expr;
+ TypeTemplDep *ttempl;
+
+ flag = 0;
+ if (tk == '[') {
+ if ((tk = lex()) == ']') {
+ len = cint64_zero;
+ tk = lex();
+ flag = 1;
+ } else {
+ if (!declinfo->x46 || declinfo->x47) {
+ expr = CExpr_IntegralConstOrDepExpr();
+ if (!ENODE_IS(expr, EINTCONST)) {
+ if (tk != ']')
+ CError_ErrorSkip(125);
+ else
+ tk = lex();
+ declinfo->x47 = 1;
+ scandirectdecl1(declinfo);
+ if (!CDecl_CheckArrayIntegr(declinfo->thetype))
+ declinfo->thetype = (Type *) &stsignedchar;
+ ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY);
+ ttempl->u.array.type = declinfo->thetype;
+ ttempl->u.array.index = CInline_CopyExpression(expr, CopyMode1);
+ declinfo->thetype = (Type *) ttempl;
+ return;
+ }
+ len = expr->data.intval;
+ if (CInt64_IsNegative(&len)) {
+ CError_Error(124);
+ len = cint64_one;
+ } else if (CInt64_IsZero(&len)) {
+ if (!copts.ANSI_strict && declinfo->x50) {
+ flag = 1;
+ } else {
+ CError_Error(124);
+ len = cint64_one;
+ }
+ }
+ } else {
+ len = cint64_one;
+ expr = expression();
+ if (IS_TYPE_INT(expr->rtype)) {
+ if (!ENODE_IS(expr, EINTCONST))
+ declinfo->x24 = expr;
+ else
+ len = expr->data.intval;
+ } else {
+ CError_Error(124);
+ }
+ }
+
+ if (tk != ']')
+ CError_ErrorSkip(125);
+ else
+ tk = lex();
+ }
+
+ declinfo->x47 = 1;
+ scandirectdecl1(declinfo);
+
+ if (!flag && !CDecl_CheckArrayIntegr(declinfo->thetype))
+ declinfo->thetype = (Type *) &stsignedchar;
+
+ if (!declinfo->thetype->size && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) {
+ ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY);
+ ttempl->u.array.type = declinfo->thetype;
+ ttempl->u.array.index = CInline_CopyExpression(intconstnode((Type *) &stsignedint, CInt64_GetULong(&len)), CopyMode1);
+ declinfo->thetype = (Type *) ttempl;
+ } else {
+ declinfo->thetype = CDecl_NewArrayType(declinfo->thetype, declinfo->thetype->size * CInt64_GetULong(&len));
+ }
+ } else if (tk == '(') {
+ if (!copts.cplusplus || !declinfo->name || IS_TYPE_VOID(declinfo->thetype) || CParser_TryParamList(!IS_TYPE_CLASS(declinfo->thetype))) {
+ tk = lex();
+ CDecl_ParseDirectFuncDecl(declinfo);
+ }
+ }
+}
+
+static void substitute_type(Type *type1, Type *type2) {
+ SInt32 oldsize;
+
+ while (1) {
+ switch (type1->type) {
+ case TYPEPOINTER:
+ if (TYPE_POINTER(type1)->target == &stillegal) {
+ TYPE_POINTER(type1)->target = type2;
+ type1->size = 4;
+ return;
+ }
+ type1 = TYPE_POINTER(type1)->target;
+ break;
+ case TYPEMEMBERPOINTER:
+ if (TYPE_MEMBER_POINTER(type1)->ty1 == &stillegal) {
+ TYPE_MEMBER_POINTER(type1)->ty1 = type2;
+ if (IS_TYPE_FUNC(type2)) {
+ CDecl_MakePTMFuncType(TYPE_FUNC(type2));
+ type1->size = 12;
+ } else {
+ type1->size = 4;
+ }
+ return;
+ }
+ type1 = TYPE_MEMBER_POINTER(type1)->ty1;
+ break;
+ case TYPEARRAY:
+ if (TYPE_POINTER(type1)->target == &stillegal) {
+ if (!CDecl_CheckArrayIntegr(type2))
+ type2 = (Type *) &stsignedchar;
+ type1->size *= type2->size;
+ TYPE_POINTER(type1)->target = type2;
+ return;
+ }
+ oldsize = TYPE_POINTER(type1)->target->size;
+ substitute_type(TYPE_POINTER(type1)->target, type2);
+ if (oldsize != TYPE_POINTER(type1)->target->size && oldsize != 0)
+ type1->size = TYPE_POINTER(type1)->target->size * (type1->size / oldsize);
+ return;
+ case TYPEFUNC:
+ if (TYPE_FUNC(type1)->functype == &stillegal) {
+ if (!checkfuncintegr(type2))
+ type2 = &stvoid;
+ TYPE_FUNC(type1)->functype = type2;
+ CDecl_SetFuncResultReg((TypeFunc *) type1);
+ return;
+ }
+ type1 = TYPE_FUNC(type1)->functype;
+ break;
+ case TYPETEMPLATE:
+ if (TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_ARRAY) {
+ if (TYPE_TEMPLATE(type1)->u.array.type == &stillegal) {
+ if (!CDecl_CheckArrayIntegr(type2))
+ type2 = (Type *) &stsignedchar;
+ TYPE_TEMPLATE(type1)->u.array.type = type2;
+ return;
+ }
+ type1 = TYPE_TEMPLATE(type1)->u.array.type;
+ } else {
+ CError_Error(146);
+ return;
+ }
+ break;
+ default:
+ CError_Error(121);
+ return;
+ }
+ }
+}
+
+static void scandecl(DeclInfo *declinfo) {
+ Type *oldtype;
+ Type *newtype;
+
+ oldtype = declinfo->thetype;
+ declinfo->thetype = &stillegal;
+ scandeclarator(declinfo);
+
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+
+ newtype = declinfo->thetype;
+ if (newtype == &stillegal) {
+ declinfo->thetype = oldtype;
+ scandirectdecl1(declinfo);
+ } else {
+ declinfo->thetype = oldtype;
+ scandirectdecl1(declinfo);
+ substitute_type(newtype, declinfo->thetype);
+ declinfo->thetype = newtype;
+ }
+}
+
+static Boolean CDecl_ParseOperatorDecl(DeclInfo *declinfo) {
+ if (declinfo->x3E) {
+ CError_Error(121);
+ return 0;
+ }
+
+ declinfo->x3E = 0;
+ if (!CParser_ParseOperatorName(&declinfo->x3E, declinfo->x4A && cscope_current->theclass, 0))
+ return 0;
+
+ if (!declinfo->x3E) {
+ conversion_type_name(declinfo);
+ tkidentifier = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual);
+ declinfo->x54 = 1;
+ }
+ return 1;
+}
+
+static Boolean CDecl_IsEnumClassTypeOrRef(Type *type) {
+ if (IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type))
+ return 1;
+ if (!IS_TYPE_REFERENCE(type))
+ return 0;
+ type = TYPE_POINTER(type)->target;
+ return IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type);
+}
+
+#define OpMysteryValue0 0
+#define OpMysteryValue1 1
+#define OpMysteryValue2 2
+#define OpMysteryValue3 3
+#define OpMysteryValue4 4
+
+static Boolean CDecl_CheckOperatorType(DeclInfo *declinfo, Boolean flag) {
+ FuncArg *args;
+ FuncArg *secondarg;
+ Type *functype;
+ short r27;
+ Boolean r6;
+
+ if (!IS_TYPE_FUNC(declinfo->thetype)) {
+ CError_Error(193);
+ return 0;
+ }
+
+ functype = TYPE_FUNC(declinfo->thetype)->functype;
+ args = TYPE_FUNC(declinfo->thetype)->args;
+ if (args) {
+ if (args != &elipsis && args != &oldstyle) {
+ r27 = OpMysteryValue1;
+ if (args->dexpr) {
+ switch (declinfo->x3E) {
+ case TK_NEW:
+ case TK_DELETE:
+ case TK_NEW_ARRAY:
+ case TK_DELETE_ARRAY:
+ break;
+ default:
+ CError_Error(205);
+ }
+ }
+
+ secondarg = args->next;
+ if (secondarg) {
+ r27 = ((secondarg != &elipsis && !secondarg->next) != 0) ? OpMysteryValue4 : OpMysteryValue3;
+ if (secondarg->dexpr) {
+ switch (declinfo->x3E) {
+ case '(':
+ case TK_NEW:
+ case TK_DELETE:
+ case TK_NEW_ARRAY:
+ case TK_DELETE_ARRAY:
+ break;
+ default:
+ CError_Error(205);
+ }
+ }
+ }
+ } else {
+ r27 = OpMysteryValue3;
+ }
+ } else {
+ CError_Error(193);
+ return 0;
+ }
+
+ r6 = flag && IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype)) && !TYPE_METHOD(declinfo->thetype)->x26;
+ switch (declinfo->x3E) {
+ case TK_NEW:
+ case TK_NEW_ARRAY:
+ if (r6 || !is_typesame(functype, (Type *) &void_ptr) || r27 < OpMysteryValue1 || args->type != CABI_GetSizeTType()) {
+ CError_Error(193);
+ return 0;
+ }
+ return 1;
+ case TK_DELETE:
+ case TK_DELETE_ARRAY:
+ if (r6 || !IS_TYPE_VOID(functype) || r27 < OpMysteryValue1 || !is_typesame(args->type, (Type *) &void_ptr)) {
+ CError_Error(193);
+ return 0;
+ }
+ return 1;
+ case '=':
+ if (!r6) {
+ CError_Error(193);
+ return 0;
+ }
+ break;
+ case '(':
+ if (!r6) {
+ CError_Error(193);
+ return 0;
+ }
+ return 1;
+ case '[':
+ if (!r6) {
+ CError_Error(193);
+ return 0;
+ }
+ break;
+ case TK_ARROW:
+ if (r27 != OpMysteryValue1 || r6 == 0) {
+ CError_Error(193);
+ return 0;
+ }
+ return 1;
+ case TK_INCREMENT:
+ case TK_DECREMENT:
+ if (r27 == OpMysteryValue2 && secondarg->type != (Type *) &stsignedint) {
+ CError_Error(193);
+ return 0;
+ }
+ break;
+ }
+
+ if (flag && !r6) {
+ CError_Error(193);
+ return 0;
+ }
+
+ switch (declinfo->x3E) {
+ case '&':
+ case '*':
+ case '+':
+ case '-':
+ case TK_INCREMENT:
+ case TK_DECREMENT:
+ if (r27 != OpMysteryValue1)
+ goto whatever;
+ case '!':
+ case '~':
+ if (r27 == OpMysteryValue1) {
+ if (flag || CDecl_IsEnumClassTypeOrRef(args->type))
+ return 1;
+ }
+ break;
+ case '%':
+ case ',':
+ case '/':
+ case '<':
+ case '=':
+ case '>':
+ case '[':
+ case '^':
+ case '|':
+ case TK_MULT_ASSIGN:
+ case TK_DIV_ASSIGN:
+ case TK_MOD_ASSIGN:
+ case TK_ADD_ASSIGN:
+ case TK_SUB_ASSIGN:
+ case TK_SHL_ASSIGN:
+ case TK_SHR_ASSIGN:
+ case TK_AND_ASSIGN:
+ case TK_XOR_ASSIGN:
+ case TK_OR_ASSIGN:
+ case TK_LOGICAL_OR:
+ case TK_LOGICAL_AND:
+ case TK_LOGICAL_EQ:
+ case TK_LOGICAL_NE:
+ case TK_LESS_EQUAL:
+ case TK_GREATER_EQUAL:
+ case TK_SHL:
+ case TK_SHR:
+ case TK_ARROW:
+ case TK_DOT_STAR:
+ case TK_ARROW_STAR:
+ whatever:
+ if (r27 == OpMysteryValue2) {
+ if (flag || CDecl_IsEnumClassTypeOrRef(args->type) || CDecl_IsEnumClassTypeOrRef(secondarg->type))
+ return 1;
+ }
+ break;
+ }
+
+ CError_Error(193);
+ return 0;
+}
+
+static void scandirectdeclarator(DeclInfo *declinfo, NameSpace *nspace) {
+ HashNameNode *saveident;
+ CScopeSave scopesave;
+ Boolean flag;
+
+ if (nspace)
+ CScope_SetNameSpaceScope(nspace, &scopesave);
+
+ if (tk == '(') {
+ if ((tk = lex()) == ')') {
+ if (declinfo->x55) {
+ CDecl_ParseDirectFuncDecl(declinfo);
+ if (nspace)
+ CScope_RestoreScope(&scopesave);
+ return;
+ } else {
+ CError_Error(121);
+ if (nspace)
+ CScope_RestoreScope(&scopesave);
+ return;
+ }
+ }
+
+ if (!(tk >= TK_AUTO && tk <= TK_BYREF)) {
+ if (!(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) {
+ scandecl(declinfo);
+ if (nspace)
+ CScope_RestoreScope(&scopesave);
+ return;
+ } else {
+ saveident = tkidentifier;
+ switch (lookahead()) {
+ case ')':
+ case ',':
+ break;
+ default:
+ tkidentifier = saveident;
+ scandecl(declinfo);
+ if (nspace)
+ CScope_RestoreScope(&scopesave);
+ return;
+ }
+ }
+ }
+
+ if (declinfo->name)
+ CError_Error(121);
+
+ CDecl_ParseDirectFuncDecl(declinfo);
+ if (nspace)
+ CScope_RestoreScope(&scopesave);
+ return;
+ }
+
+ if (nspace) {
+ if (tk == TK_OPERATOR) {
+ if (!CDecl_ParseOperatorDecl(declinfo)) {
+ CScope_RestoreScope(&scopesave);
+ return;
+ }
+
+ if (declinfo->x54) {
+ declinfo->nspace = nspace;
+ declinfo->name = tkidentifier;
+ if (nspace)
+ CScope_RestoreScope(&scopesave);
+
+ if (tk == '(') {
+ tk = lex();
+ CDecl_ParseDirectFuncDecl(declinfo);
+ if (IS_TYPE_FUNC(declinfo->thetype))
+ TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_40;
+ else
+ CError_Error(121);
+ } else {
+ CError_Error(114);
+ }
+ return;
+ }
+
+ flag = 1;
+ } else if (tk != TK_IDENTIFIER) {
+ CError_Error(107);
+ CScope_RestoreScope(&scopesave);
+ return;
+ } else {
+ flag = 0;
+ }
+
+ if (declinfo->name) {
+ CError_Error(121);
+ CScope_RestoreScope(&scopesave);
+ return;
+ }
+
+ declinfo->nspace = nspace;
+ declinfo->name = tkidentifier;
+ if (!flag)
+ tk = lex();
+ } else if (tk == TK_IDENTIFIER) {
+ if (declinfo->name)
+ CError_Error(121);
+ declinfo->name = tkidentifier;
+ tk = lex();
+ } else if (tk == TK_OPERATOR) {
+ if (!CDecl_ParseOperatorDecl(declinfo))
+ return;
+ declinfo->name = tkidentifier;
+ }
+
+ if (tk == '<' && declinfo->x51) {
+ declinfo->expltargs = CTempl_ParseUncheckTemplArgs(NULL, 0);
+ declinfo->has_expltargs = 1;
+ declinfo->x51 = 0;
+ tk = lex();
+ }
+
+ scandirectdecl1(declinfo);
+
+ if (nspace)
+ CScope_RestoreScope(&scopesave);
+}
+
+void makememberpointertype(DeclInfo *declinfo, TypeClass *tclass, UInt32 qual) {
+ TypeMemberPointer *tmemp;
+ TypeFunc *tfunc;
+
+ if (tclass->flags & CLASS_FLAGS_1) {
+ CError_Error(191);
+ declinfo->thetype = (Type *) &stsignedint;
+ return;
+ }
+ if (tclass->sominfo) {
+ CError_Error(290);
+ declinfo->thetype = (Type *) &stsignedint;
+ return;
+ }
+
+ tmemp = galloc(sizeof(TypeMemberPointer));
+ memclrw(tmemp, sizeof(TypeMemberPointer));
+ tmemp->type = TYPEMEMBERPOINTER;
+ tmemp->ty2 = (Type *) tclass;
+ tmemp->qual = qual;
+
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ tfunc = galloc(sizeof(TypeFunc));
+ *tfunc = *TYPE_FUNC(declinfo->thetype);
+ tmemp->ty1 = (Type *) tfunc;
+ tmemp->size = 12;
+ CDecl_MakePTMFuncType(tfunc);
+ } else {
+ tmemp->size = 4;
+ tmemp->ty1 = declinfo->thetype;
+ }
+ declinfo->thetype = (Type *) tmemp;
+}
+
+void CDecl_ScanPointer(DeclInfo *declinfo, NameSpace *nspace, Boolean flag) {
+ CScopeParseResult pr;
+ UInt32 qual;
+
+ while (1) {
+ qual = (tk == '&') ? Q_REFERENCE : 0;
+
+ for (tk = lex(); ; tk = lex()) {
+ switch (tk) {
+ case TK_CONST:
+ if (qual & Q_CONST)
+ CError_Error(121);
+ qual |= Q_CONST;
+ continue;
+ case TK_VOLATILE:
+ if (qual & Q_VOLATILE)
+ CError_Error(121);
+ qual |= Q_VOLATILE;
+ continue;
+ case TK_RESTRICT:
+ if (qual & Q_RESTRICT)
+ CError_Error(121);
+ qual |= Q_RESTRICT;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (IS_TYPE_REFERENCE(declinfo->thetype) || ((qual & Q_REFERENCE) && IS_TYPE_VOID(declinfo->thetype))) {
+ CError_Error(196);
+ return;
+ }
+
+ if (nspace) {
+ makememberpointertype(declinfo, nspace->theclass, qual);
+ nspace = NULL;
+ } else {
+ makethetypepointer(declinfo, qual);
+ }
+
+ switch (tk) {
+ case '*':
+ continue;
+ case '&':
+ if (!copts.cplusplus) {
+ if (flag)
+ scandirectdeclarator(declinfo, NULL);
+ return;
+ }
+ continue;
+ case TK_IDENTIFIER:
+ if (!copts.cplusplus)
+ break;
+ if (copts.cpp_extensions && cscope_current->theclass && cscope_current->theclass->classname == tkidentifier && lookahead() == TK_COLON_COLON) {
+ tk = lex();
+ tk = lex();
+ break;
+ }
+ case TK_COLON_COLON:
+ if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) {
+ if ((nspace = pr.nspace_0)) {
+ if (nspace->theclass && tk == '*')
+ continue;
+ } else {
+ if (pr.x8 && IS_TYPE_TEMPLATE(pr.x8) && declinfo->x30) {
+ if (CTempl_IsQualifiedMember(declinfo, pr.x8, &nspace))
+ scandirectdeclarator(declinfo, nspace);
+ else
+ declinfo->x20 = pr.x8;
+ return;
+ }
+ CError_Error(121);
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ if (flag)
+ scandirectdeclarator(declinfo, nspace);
+}
+
+static void CDecl_TemplatePTM(DeclInfo *declinfo, Type *type) {
+ TypeMemberPointer *tmemp = galloc(sizeof(TypeMemberPointer));
+ tmemp->type = TYPEMEMBERPOINTER;
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ CDecl_MakePTMFuncType((TypeFunc *) declinfo->thetype);
+ tmemp->size = 12;
+ } else {
+ tmemp->size = 4;
+ }
+
+ tmemp->ty1 = declinfo->thetype;
+ tmemp->ty2 = type;
+ tmemp->qual = 0;
+ declinfo->thetype = (Type *) tmemp;
+}
+
+void scandeclarator(DeclInfo *declinfo) {
+ CScopeParseResult pr;
+ NameSpace *nspace;
+
+ switch (tk) {
+ case '&':
+ if (!copts.cplusplus)
+ break;
+ case '*':
+ CDecl_ScanPointer(declinfo, NULL, 1);
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(NULL, declinfo);
+ return;
+ case TK_IDENTIFIER:
+ if (!copts.cplusplus)
+ break;
+ case TK_COLON_COLON:
+ if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) {
+ nspace = pr.nspace_0;
+ if (nspace) {
+ if (nspace->theclass && tk == '*')
+ CDecl_ScanPointer(declinfo, nspace, 1);
+ else
+ scandirectdeclarator(declinfo, nspace);
+ return;
+ }
+ if (pr.x8 && IS_TYPE_TEMPLATE(pr.x8)) {
+ if (declinfo->x30 && CTempl_IsQualifiedMember(declinfo, pr.x8, &nspace)) {
+ scandirectdeclarator(declinfo, nspace);
+ return;
+ } else if (declinfo->x30 && tk == TK_OPERATOR) {
+ declinfo->x20 = pr.x8;
+ return;
+ } else if ((tk = lex()) == TK_COLON_COLON && (tk = lex()) == '*') {
+ CDecl_TemplatePTM(declinfo, pr.x8);
+ tk = lex();
+ break;
+ } else if (declinfo->x30) {
+ declinfo->x20 = pr.x8;
+ return;
+ }
+ }
+ CError_Error(121);
+ }
+ break;
+ }
+
+ scandirectdeclarator(declinfo, NULL);
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(NULL, declinfo);
+}
+
+void conversion_type_name(DeclInfo *declinfo) {
+ CScopeParseResult pr;
+ DeclInfo subdeclinfo;
+
+ memclrw(&subdeclinfo, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&subdeclinfo, 0);
+
+ switch (tk) {
+ case '&':
+ case '*':
+ CDecl_ScanPointer(&subdeclinfo, NULL, 0);
+ break;
+ case TK_IDENTIFIER:
+ case TK_COLON_COLON:
+ if (CScope_ParseQualifiedNameSpace(&pr, 0, 0)) {
+ if (pr.nspace_0 && pr.nspace_0->theclass && tk == '*')
+ CDecl_ScanPointer(&subdeclinfo, pr.nspace_0, 0);
+ else
+ CError_Error(121);
+ }
+ break;
+ }
+
+ declinfo->name = subdeclinfo.name;
+ declinfo->thetype = subdeclinfo.thetype;
+ declinfo->qual |= subdeclinfo.qual;
+}
+
+static void scaninlinefunc(Object *obj) {
+ short array[256];
+ short r29;
+ CInt64 val;
+
+ if (tk == '{') {
+ tk = lex();
+ r29 = 0;
+ while (1) {
+ if (r29 >= 256) {
+ CError_Error(127);
+ r29 = 255;
+ }
+ val = CExpr_IntegralConstExpr();
+ array[r29++] = CInt64_GetULong(&val);
+ if (tk != '}') {
+ if (tk != ',')
+ CError_Error(116);
+ tk = lex();
+ } else {
+ tk = lex();
+ break;
+ }
+ }
+ } else {
+ val = CExpr_IntegralConstExpr();
+ array[0] = CInt64_GetULong(&val);
+ r29 = 1;
+ }
+
+ obj->datatype = DINLINEFUNC;
+ obj->u.ifunc.size = r29 * 2;
+ obj->u.ifunc.data = galloc(obj->u.ifunc.size);
+ obj->u.ifunc.xrefs = NULL;
+ memcpy(obj->u.ifunc.data, array, obj->u.ifunc.size);
+
+ if (tk != ';')
+ CError_Error(123);
+}
+
+typedef enum {
+ OverloadMode0,
+ OverloadMode1,
+ OverloadMode2,
+ OverloadMode3
+} OverloadMode;
+
+static Object *CDecl_OverloadFunctionObject(NameSpaceObjectList *list, DeclInfo *declinfo, Boolean *outflag, OverloadMode mode, Boolean flag2) {
+ TypeFunc *scanfunc;
+ NameSpaceObjectList *scan;
+ TypeFunc *tfunc;
+ FuncArg *args;
+ FuncArg *scanargs;
+ Object *obj;
+ Boolean r24;
+ short compareresult;
+
+ if (outflag)
+ *outflag = 0;
+
+ tfunc = (TypeFunc *) declinfo->thetype;
+ args = tfunc->args;
+ r24 = 0;
+ for (scan = list; scan; scan = scan->next) {
+ obj = OBJECT(scan->object);
+ if (obj->otype != OT_OBJECT)
+ continue;
+
+ scanfunc = TYPE_FUNC(obj->type);
+ if (!IS_TYPE_FUNC(scanfunc))
+ continue;
+
+ scanargs = scanfunc->args;
+ if (scanfunc->flags & FUNC_FLAGS_100000)
+ r24 = 1;
+
+ if (IS_TYPEFUNC_METHOD(scanfunc)) {
+ switch (mode) {
+ case OverloadMode0:
+ CError_Error(197);
+ break;
+ case OverloadMode1:
+ if (!TYPE_METHOD(scanfunc)->x26)
+ continue;
+ break;
+ case OverloadMode2:
+ if (TYPE_METHOD(scanfunc)->x26)
+ continue;
+ break;
+ case OverloadMode3:
+ if (!TYPE_METHOD(scanfunc)->x26) {
+ if (scanargs->qual & (Q_CONST | Q_VOLATILE))
+ continue;
+ scanargs = scanargs->next;
+ }
+ break;
+ }
+ } else {
+ if (mode)
+ CError_Error(197);
+ }
+
+ compareresult = CParser_CompareArgLists(args, scanargs);
+ if (compareresult == 1) {
+ if (scanfunc->flags & FUNC_FLAGS_40) {
+ if (!(tfunc->flags & FUNC_FLAGS_40)) {
+ CError_Error(197);
+ break;
+ }
+ if (!is_typesame(tfunc->functype, scanfunc->functype))
+ continue;
+ if ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL)))
+ continue;
+ if ((tfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (scanfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) {
+ CError_Error(197);
+ break;
+ }
+ if (tfunc->exspecs || scanfunc->exspecs)
+ CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs);
+ return obj;
+ }
+
+ if (tfunc->flags & FUNC_FLAGS_40) {
+ CError_Error(197);
+ break;
+ }
+
+ if (!is_typesame(tfunc->functype, scanfunc->functype) || ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL))) || ((tfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (scanfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))) {
+ CError_Error(197);
+ break;
+ }
+
+ if (tfunc->exspecs || scanfunc->exspecs) {
+ if (obj->name != newp_fobj->name && obj->name != newa_fobj->name && obj->name != delp_fobj->name && obj->name != dela_fobj->name)
+ CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs);
+ }
+
+ return obj;
+ } else if (compareresult == 2) {
+ CError_Error(197);
+ break;
+ }
+ }
+
+ if (r24 && (flag2 || declinfo->x3C)) {
+ if ((obj = CTempl_TemplateFunctionCheck(declinfo, list)))
+ return obj;
+ }
+
+ if (!outflag) {
+ CError_Error(197);
+ return NULL;
+ }
+
+ if (declinfo->nspace)
+ CError_Error(336);
+
+ *outflag = 1;
+ obj = CParser_NewFunctionObject(declinfo);
+ CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
+
+ if (tfunc->flags & FUNC_FLAGS_PASCAL) {
+ for (scan = list; scan; scan = scan->next) {
+ if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) {
+ if (TYPE_FUNC(OBJECT(scan->object)->type)->flags & FUNC_FLAGS_PASCAL)
+ CError_Error(226);
+ }
+ }
+ }
+
+ if (copts.cplusplus && declinfo->x4E) {
+ for (scan = list; scan; scan = scan->next) {
+ if (scan->object->otype == OT_OBJECT && !(OBJECT(scan->object)->qual & Q_80000))
+ CError_Error(197);
+ }
+ }
+
+ CScope_AddObject(cscope_current, declinfo->name, OBJ_BASE(obj));
+ if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100) &&
+ CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
+ CTemplClass_RegisterObjectDef(TEMPL_CLASS(cscope_current->theclass), OBJ_BASE(obj));
+
+ return obj;
+}
+
+void MergeDefaultArgs(FuncArg *a, FuncArg *b) {
+ FuncArg *scan_a;
+ FuncArg *scan_b;
+
+ if (a == &oldstyle || b == &oldstyle)
+ return;
+
+ scan_a = a;
+ scan_b = b;
+ while (scan_a && scan_b) {
+ if (scan_a->dexpr) {
+ while (scan_b) {
+ if (scan_b->dexpr) {
+ while (a) {
+ a->dexpr = NULL;
+ a = a->next;
+ }
+ while (b) {
+ b->dexpr = NULL;
+ b = b->next;
+ }
+ CError_Error(205);
+ return;
+ }
+ scan_b = scan_b->next;
+ }
+ break;
+ } else if (scan_b->dexpr) {
+ do {
+ scan_a = scan_a->next;
+ scan_b = scan_b->next;
+ if (!scan_a) goto secondpart;
+ if (scan_a == &elipsis) goto secondpart;
+ if (scan_a->dexpr && scan_b->dexpr) break;
+ } while (scan_a->dexpr || scan_b->dexpr);
+
+ while (a) {
+ a->dexpr = NULL;
+ a = a->next;
+ }
+ while (b) {
+ b->dexpr = NULL;
+ b = b->next;
+ }
+ CError_Error(205);
+ return;
+ } else {
+ scan_a = scan_a->next;
+ scan_b = scan_b->next;
+ }
+ }
+
+secondpart:
+ while (a && b) {
+ if (b->dexpr)
+ a->dexpr = b->dexpr;
+ else
+ b->dexpr = a->dexpr;
+ a = a->next;
+ b = b->next;
+ }
+}
+
+void CheckDefaultArgs(FuncArg *args) {
+ FuncArg *scan;
+
+ scan = args;
+ while (scan && !scan->dexpr)
+ scan = scan->next;
+
+ while (scan && scan != &elipsis && scan != &oldstyle) {
+ if (!scan->dexpr) {
+ while (args) {
+ args->dexpr = NULL;
+ args = args->next;
+ }
+ CError_Error(205);
+ return;
+ }
+ scan = scan->next;
+ }
+}
+
+static void CDecl_FuncRedeclCheck(Object *obj, DeclInfo *declinfo, Boolean flag) {
+ if (declinfo->storageclass == OBJECT_SCLASS_102 && obj->sclass != OBJECT_SCLASS_102) {
+ if (copts.cplusplus)
+ CError_Error(260);
+ else
+ obj->sclass = OBJECT_SCLASS_102;
+ }
+
+ obj->qual |= declinfo->qual;
+ if (flag)
+ CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
+ else
+ MergeDefaultArgs(TYPE_FUNC(obj->type)->args, TYPE_FUNC(declinfo->thetype)->args);
+
+ if (!declinfo->x45)
+ TYPE_FUNC(obj->type)->args = TYPE_FUNC(declinfo->thetype)->args;
+}
+
+Object *CDecl_GetFunctionObject(DeclInfo *declinfo, NameSpace *nspace, Boolean *pflag, Boolean someotherflag) {
+ Boolean r27;
+ Object *obj;
+ Type *type;
+ NameSpace *nspace2;
+ NameSpaceObjectList *list;
+ TypeMethod tmp;
+ Boolean outflag;
+
+ r27 = 0;
+ if (pflag)
+ *pflag = 0;
+
+ nspace2 = declinfo->nspace;
+ if (!nspace2)
+ nspace2 = cscope_current;
+
+ CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_INLINE | Q_PASCAL | Q_ASM | Q_VOLATILE | Q_CONST));
+ switch (TYPE_FUNC(declinfo->thetype)->functype->type) {
+ case TYPEFUNC:
+ case TYPEARRAY:
+ CError_Error(128);
+ TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint;
+ break;
+ }
+
+ if (nspace2->theclass) {
+#line 1969
+ CError_ASSERT(declinfo->name);
+ if (!nspace2->theclass->size)
+ CDecl_CompleteType((Type *) nspace2->theclass);
+ if (!(list = CScope_GetLocalObject(nspace2, declinfo->name))) {
+ CError_Error(140, declinfo->name->name);
+ return NULL;
+ }
+
+ obj = OBJECT(list->object);
+ type = obj->type;
+ if (!IS_TYPE_FUNC(type)) {
+ CError_Error(249, CError_GetObjectName(obj), type, obj->qual, declinfo->thetype, declinfo->qual);
+ return NULL;
+ }
+
+ if (declinfo->has_expltargs)
+ return CTempl_TemplateFunctionCheck(declinfo, list);
+
+ if (declinfo->x3C || (list->next && list->next->object->otype == OT_OBJECT)) {
+ if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_FLAGS_CONST | FUNC_FLAGS_VOLATILE)) {
+ CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass);
+ obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode2, someotherflag);
+ if (!obj)
+ return NULL;
+ } else {
+ obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode3, someotherflag);
+ if (!obj)
+ return NULL;
+ if (!TYPE_METHOD(obj->type)->x26)
+ CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass);
+ }
+ } else {
+ if (TYPE_METHOD(type)->x26) {
+ if (nspace2->theclass->sominfo)
+ CSOM_FixNewDeleteFunctype(TYPE_FUNC(declinfo->thetype));
+ } else {
+ CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass);
+ }
+
+ if (copts.cpp_extensions) {
+ declinfo->qual |= obj->qual & (Q_PASCAL | Q_CONST);
+ TYPE_FUNC(declinfo->thetype)->qual |= TYPE_FUNC(obj->type)->qual & (Q_PASCAL | Q_CONST);
+ TYPE_FUNC(declinfo->thetype)->flags |= TYPE_FUNC(obj->type)->flags & (FUNC_FLAGS_4000000 | FUNC_FLAGS_10000000);
+ }
+
+ if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_PASCAL | Q_CONST)) != (obj->qual & (Q_PASCAL | Q_CONST))) {
+ tmp = *TYPE_METHOD(obj->type);
+ *(TYPE_FUNC(&tmp)) = *TYPE_FUNC(declinfo->thetype);
+ tmp.flags |= FUNC_FLAGS_METHOD;
+ CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, &tmp, declinfo->qual);
+ }
+
+ if (TYPE_FUNC(declinfo->thetype)->exspecs || TYPE_FUNC(obj->type)->exspecs)
+ CExcept_CompareSpecifications(TYPE_FUNC(declinfo->thetype)->exspecs, TYPE_FUNC(obj->type)->exspecs);
+ }
+
+ CDecl_FuncRedeclCheck(obj, declinfo, 0);
+ if (declinfo->x3C) {
+ if (obj->nspace->theclass && !(obj->nspace->theclass->flags & CLASS_FLAGS_800))
+ CError_Error(335);
+ declinfo->x3C = 0;
+ }
+ } else {
+ if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_FLAGS_VOLATILE | FUNC_FLAGS_CONST))
+ CError_Error(384);
+
+ if (declinfo->x3E && !CDecl_CheckOperatorType(declinfo, 0))
+ return NULL;
+
+ list = CScope_GetLocalObject(nspace2, declinfo->name);
+ if (declinfo->has_expltargs)
+ return CTempl_TemplateFunctionCheck(declinfo, list);
+
+ if (list) {
+ if (copts.cplusplus) {
+ obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, OverloadMode0, someotherflag);
+ if (!obj)
+ return NULL;
+ if (pflag)
+ *pflag = outflag;
+ if (nspace)
+ obj->nspace = nspace;
+ } else {
+ obj = OBJECT(list->object);
+ if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_CONST | Q_PASCAL)) != (obj->qual & (Q_CONST | Q_PASCAL))) {
+ CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual);
+ r27 = 1;
+ if (!IS_TYPE_FUNC(obj->type))
+ return NULL;
+ }
+ }
+
+ if (!r27 && pflag)
+ CDecl_FuncRedeclCheck(obj, declinfo, *pflag);
+ } else {
+ if (declinfo->nspace)
+ CError_Error(336);
+
+ if (declinfo->has_expltargs) {
+ if (declinfo->name)
+ CError_Error(140, declinfo->name->name);
+ else
+ CError_Error(127);
+ }
+
+ obj = CParser_NewFunctionObject(declinfo);
+ if (nspace)
+ obj->nspace = nspace;
+ if (pflag)
+ *pflag = 1;
+ else
+ CError_Error(127);
+
+ CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
+ CScope_AddObject(nspace2, declinfo->name, OBJ_BASE(obj));
+ }
+ }
+
+ return obj;
+}
+
+void CDecl_TypedefDeclarator(DeclInfo *declinfo) {
+ NameSpace *nspace;
+ NameSpaceObjectList *list;
+ ObjType *objt;
+
+ nspace = declinfo->nspace;
+ if (!nspace)
+ nspace = cscope_current;
+
+ CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST));
+ if (declinfo->x48 || declinfo->x44)
+ CError_Error(121);
+ if (declinfo->x3E)
+ CError_Error(193);
+
+ objt = NULL;
+ list = CScope_FindName(nspace, declinfo->name);
+ if (list) {
+ switch (list->object->otype) {
+ case OT_TYPE:
+ objt = OBJ_TYPE(list->object);
+ break;
+ case OT_TYPETAG:
+ break;
+ case OT_NAMESPACE:
+ CError_Error(321);
+ return;
+ case OT_ENUMCONST:
+ case OT_OBJECT:
+ CError_Error(322);
+ return;
+ default:
+#line 2156
+ CError_FATAL();
+ }
+ }
+
+ if (objt) {
+ const UInt32 mask = Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST;
+ if (!is_typesame(objt->type, declinfo->thetype) || (objt->qual & mask) != (declinfo->qual & mask)) {
+ CError_Error(249, declinfo->name->name, objt->type, objt->qual, declinfo->thetype, declinfo->qual);
+ } else if (!copts.cplusplus && (copts.pedantic || copts.ANSI_strict)) {
+ if (copts.pedantic)
+ CError_Warning(122, declinfo->name->name);
+ else
+ CError_Error(122, declinfo->name->name);
+ }
+ return;
+ }
+
+ objt = galloc(sizeof(ObjType));
+ memclrw(objt, sizeof(ObjType));
+ objt->otype = OT_TYPE;
+ objt->access = ACCESSPUBLIC;
+ objt->type = declinfo->thetype;
+ objt->qual = declinfo->qual;
+ CScope_AddObject(nspace, declinfo->name, OBJ_BASE(objt));
+
+ if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100) &&
+ CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
+ CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(objt));
+
+ if (copts.cplusplus) {
+ if (IS_TYPE_CLASS(declinfo->thetype) && IsTempName(TYPE_CLASS(declinfo->thetype)->classname)) {
+ TYPE_CLASS(declinfo->thetype)->classname = declinfo->name;
+ TYPE_CLASS(declinfo->thetype)->nspace->name = declinfo->name;
+ }
+ if (IS_TYPE_ENUM(declinfo->thetype) && IsTempName(TYPE_ENUM(declinfo->thetype)->enumname)) {
+ TYPE_ENUM(declinfo->thetype)->enumname = declinfo->name;
+ }
+ }
+
+ if (cparamblkptr->browseOptions.recordTypedefs && declinfo->fileoffsetinfo.file->recordbrowseinfo)
+ CBrowse_NewTypedef(nspace, declinfo->name, declinfo->fileoffsetinfo.file, declinfo->fileoffsetinfo.tokenline, declinfo->fileoffsetinfo.tokenoffset, CPrep_BrowserFileOffset());
+}
+
+static void CDecl_DataDeclarator(DeclInfo *declinfo, short access, Boolean flag) {
+ NameSpaceObjectList *list;
+ Object *obj;
+ NameSpace *nspace;
+ Boolean tmpflag;
+ ENode *expr;
+
+ nspace = declinfo->nspace;
+ if (!nspace)
+ nspace = cscope_current;
+
+ CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST));
+ if (declinfo->x48 || declinfo->x44)
+ CError_Error(121);
+ if (declinfo->x3E)
+ CError_Error(193);
+
+ obj = NULL;
+ list = CScope_FindName(nspace, declinfo->name);
+ if (list) {
+ switch (list->object->otype) {
+ case OT_OBJECT:
+ obj = OBJECT(list->object);
+ if (flag)
+ CError_Error(122, declinfo->name->name);
+ break;
+ case OT_TYPETAG:
+ break;
+ case OT_NAMESPACE:
+ CError_Error(321);
+ return;
+ case OT_ENUMCONST:
+ case OT_TYPE:
+ CError_Error(322);
+ break;
+ case OT_MEMBERVAR:
+ CError_Error(221);
+ break;
+ default:
+#line 2281
+ CError_FATAL();
+ }
+ }
+
+ if (copts.cplusplus) {
+ if (!flag)
+ CDecl_CompleteType(declinfo->thetype);
+ switch (declinfo->storageclass) {
+ case OBJECT_SCLASS_103:
+ if (tk == '=' || tk == '(')
+ declinfo->storageclass = 0;
+ break;
+ case 0:
+ if (CParser_IsConst(declinfo->thetype, declinfo->qual)) {
+ if ((!obj && !nspace->theclass) || (obj && obj->sclass != OBJECT_SCLASS_103 && !obj->nspace->theclass))
+ declinfo->storageclass = OBJECT_SCLASS_102;
+ }
+ break;
+ }
+ } else {
+ if (declinfo->storageclass == OBJECT_SCLASS_103 && tk == '=')
+ declinfo->storageclass = 0;
+ }
+
+ if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size && !declinfo->storageclass && tk != '=')
+ declinfo->storageclass = OBJECT_SCLASS_103;
+
+ if (obj) {
+ if ((!obj->type->size || !declinfo->thetype->size) && IS_TYPE_ARRAY(declinfo->thetype) && IS_TYPE_ARRAY(obj->type))
+ tmpflag = is_typesame(TYPE_POINTER(declinfo->thetype)->target, TYPE_POINTER(obj->type)->target);
+ else
+ tmpflag = is_typesame(declinfo->thetype, obj->type);
+
+ if (!tmpflag || (obj->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST)) != (declinfo->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST)))
+ CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual);
+
+ if (obj->qual & Q_10000) {
+ if (tk == ',' || tk == ';')
+ return;
+ CError_Error(333, obj);
+ }
+
+ if (declinfo->storageclass != OBJECT_SCLASS_103) {
+ if (obj->sclass != OBJECT_SCLASS_103 && declinfo->storageclass && obj->sclass != declinfo->storageclass)
+ CError_Error(333, obj);
+
+ if (tmpflag) {
+ obj->sclass = declinfo->storageclass;
+ obj->qual |= declinfo->qual;
+ if (declinfo->thetype->size)
+ obj->type = declinfo->thetype;
+ }
+
+ CParser_UpdateObject(obj, declinfo);
+ } else {
+ flag = 1;
+ }
+ } else {
+ if (declinfo->nspace)
+ CError_Error(336);
+ if (IS_TYPE_CLASS(declinfo->thetype) && TYPE_CLASS(declinfo->thetype)->sominfo)
+ CError_Error(288);
+ if (!CanCreateObject(declinfo->thetype))
+ declinfo->thetype = (Type *) &stsignedint;
+
+ obj = CParser_NewGlobalDataObject(declinfo);
+ obj->access = access;
+ CScope_AddObject(nspace, declinfo->name, OBJ_BASE(obj));
+
+ if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100) &&
+ CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
+ CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(obj));
+
+ if (flag && nspace->theclass && cparamblkptr->browseOptions.recordClasses)
+ CBrowse_AddClassMemberData(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
+ }
+
+ if (!flag) {
+ if (declinfo->nspace) {
+ CScopeSave save;
+ CScope_SetNameSpaceScope(declinfo->nspace, &save);
+ CInit_InitializeData(obj);
+ CScope_RestoreScope(&save);
+
+ if (declinfo->x3C && obj->nspace->theclass && (TYPE_CLASS(obj->nspace->theclass)->flags & CLASS_FLAGS_800))
+ declinfo->x3C = 0;
+ } else {
+ CInit_InitializeData(obj);
+ }
+
+ if (declinfo->fileoffsetinfo.file->recordbrowseinfo && obj->sclass != OBJECT_SCLASS_103)
+ CBrowse_NewData(obj, declinfo->fileoffsetinfo.file, declinfo->fileoffsetinfo.tokenline, declinfo->fileoffsetinfo.tokenoffset, CPrep_BrowserFileOffset());
+ } else if (tk == '=') {
+ tk = lex();
+ expr = CExpr_IntegralConstOrDepExpr();
+ if (IS_TYPE_TEMPLATE(obj->type) || !ENODE_IS(expr, EINTCONST)) {
+#line 2426
+ CError_ASSERT(nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100));
+ CTemplClass_RegisterObjectInit(TEMPL_CLASS(nspace->theclass), OBJ_BASE(obj), expr);
+ } else if ((obj->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(obj->type)) {
+ obj->u.data.u.intconst = expr->data.intval;
+ obj->qual |= Q_10000 | Q_20000;
+ } else {
+ CError_Error(354, obj->name->name);
+ }
+ }
+}
+
+Boolean CDecl_FunctionDeclarator(DeclInfo *declinfo, NameSpace *nspace, Boolean flag, Boolean flag2) {
+ Object *obj;
+ Boolean pflag;
+
+ obj = CDecl_GetFunctionObject(declinfo, nspace, &pflag, 0);
+ if (obj) {
+ if (declinfo->x44 || tk == '{' || tk == TK_TRY || (declinfo->x4B && tk == ':') || (!copts.cplusplus && isdeclaration(0, 0, 0, 0))) {
+ if (!flag || cscope_currentfunc) {
+ CError_Error(127);
+ if (cscope_currentfunc)
+ return 0;
+ }
+
+ if (obj->nspace == cscope_root && !strcmp(obj->name->name, "main")) {
+ if (obj->sclass == OBJECT_SCLASS_102 || (copts.ANSI_strict && TYPE_FUNC(obj->type)->functype != (Type *) &stsignedint))
+ CError_Error(334);
+ } else if (copts.require_prototypes && (pflag || declinfo->fileoffsetinfo.is_inline)) {
+ if (obj->sclass != OBJECT_SCLASS_102 && !(obj->qual & Q_INLINE) && !obj->nspace->is_unnamed)
+ CError_Warning(178);
+ }
+
+ CFunc_ParseFuncDef(obj, declinfo, NULL, 0, 0, NULL);
+ // WARNING: WEIRD FileOffsetInfo ALERT
+ if (declinfo->fileoffsetinfo.file->recordbrowseinfo)
+ CBrowse_NewFunction(
+ obj,
+ declinfo->fileoffsetinfo.file,
+ (CPrepFileInfo *) declinfo->fileoffsetinfo.tokenline,
+ declinfo->fileoffsetinfo.tokenoffset,
+ CPrep_BrowserFileOffset());
+
+ if (copts.cplusplus && lookahead() == ';')
+ tk = lex();
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void CDecl_ParseSpecialMember(DeclInfo *declinfo, Boolean flag) {
+ Object *r28;
+ NameSpace *r25;
+
+ if (!(r28 = declinfo->x10)) {
+#line 2544
+ CError_ASSERT(declinfo->x14);
+ r28 = declinfo->x14->object;
+#line 2546
+ CError_ASSERT(r28->otype == OT_OBJECT);
+ }
+
+ if (!r28->nspace->theclass) {
+ CError_Error(121);
+ return;
+ }
+
+ if (IS_TYPE_FUNC(r28->type)) {
+ if (TYPE_FUNC(r28->type)->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000)) {
+ if (r28->nspace->theclass->sominfo)
+ declinfo->thetype = TYPE(&stvoid);
+ else
+ declinfo->thetype = TYPE(&void_ptr);
+ declinfo->nspace = r28->nspace;
+ declinfo->name = r28->name;
+ if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_1000)
+ declinfo->x4B = 1;
+
+ if ((tk = lex()) == '(') {
+ tk = lex();
+
+ r25 = cscope_current;
+ cscope_current = r28->nspace;
+ CDecl_ParseDirectFuncDecl(declinfo);
+ cscope_current = r25;
+
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_1000) {
+ if ((r28->nspace->theclass->flags & CLASS_FLAGS_20) && !r28->nspace->theclass->sominfo)
+ CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort));
+ } else {
+ if (!r28->nspace->theclass->sominfo)
+ CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort));
+ }
+ if (flag)
+ CDecl_FunctionDeclarator(declinfo, NULL, 1, 1);
+ } else {
+ CError_Error(121);
+ }
+ } else {
+ CError_Error(114);
+ }
+ return;
+ } else if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_40) {
+#line 2603
+ CError_FATAL();
+
+ declinfo->thetype = TYPE_FUNC(r28->type)->functype;
+ declinfo->qual |= TYPE_FUNC(r28->type)->qual;
+ declinfo->nspace = r28->nspace;
+ declinfo->name = r28->name;
+
+ if ((tk = lex()) == '(') {
+ tk = lex();
+ CDecl_ParseDirectFuncDecl(declinfo);
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_40;
+ if (flag)
+ CDecl_FunctionDeclarator(declinfo, NULL, 1, 1);
+ } else {
+ CError_Error(121);
+ }
+ } else {
+ CError_Error(114);
+ }
+ return;
+ } else {
+ declinfo->thetype = TYPE(&stsignedint);
+ declinfo->nspace = r28->nspace;
+ declinfo->name = r28->name;
+
+ if ((tk = lex()) == '(') {
+ tk = lex();
+
+ r25 = cscope_current;
+ cscope_current = r28->nspace;
+ CDecl_ParseDirectFuncDecl(declinfo);
+ cscope_current = r25;
+
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ if (flag)
+ CDecl_FunctionDeclarator(declinfo, NULL, 1, 1);
+ return;
+ }
+ } else {
+ CError_Error(114);
+ }
+ }
+ }
+
+ CError_Error(121);
+}
+
+void CDecl_ScanDeclarator(DeclInfo *declinfo) {
+ if (declinfo->x14 || declinfo->x10) {
+ CDecl_ParseSpecialMember(declinfo, 0);
+ CDecl_GetFunctionObject(declinfo, NULL, NULL, 1);
+ return;
+ }
+
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ TypeFunc *copy = galloc(sizeof(TypeFunc));
+ *copy = *TYPE_FUNC(declinfo->thetype);
+ declinfo->thetype = TYPE(copy);
+ }
+ scandeclarator(declinfo);
+ if (!declinfo->name) {
+ CError_Error(121);
+ return;
+ }
+
+ if (declinfo->storageclass && declinfo->storageclass != OBJECT_SCLASS_103)
+ CError_Error(177);
+
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ CDecl_GetFunctionObject(declinfo, NULL, NULL, 1);
+ return;
+ }
+
+ if (declinfo->x48 || declinfo->x44)
+ CError_Error(121);
+
+ if (declinfo->x3E)
+ CError_Error(193);
+
+ if (
+ (declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)) ||
+ (declinfo->storageclass == OBJECT_SCLASS_104 && (declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST)))
+ )
+ CError_Error(176);
+}
+
+void scandeclaratorlist(DeclInfo *declinfo) {
+ CScopeSave savescope;
+ Type *r30;
+ UInt32 r29;
+ Boolean r28;
+
+ if (declinfo->x14 || declinfo->x10) {
+ CDecl_ParseSpecialMember(declinfo, 1);
+ return;
+ }
+
+ CScope_GetScope(&savescope);
+#line 2707
+ CError_ASSERT(declinfo->thetype);
+
+ r28 = 1;
+ while (1) {
+ r30 = declinfo->thetype;
+ r29 = declinfo->qual;
+ declinfo->nspace = NULL;
+ declinfo->x3E = 0;
+ if (IS_TYPE_FUNC(r30)) {
+ declinfo->thetype = galloc(sizeof(TypeFunc));
+ *TYPE_FUNC(declinfo->thetype) = *TYPE_FUNC(r30);
+ }
+ declinfo->name = NULL;
+ scandeclarator(declinfo);
+ if (!declinfo->name) {
+ CError_Error(121);
+ break;
+ }
+
+ if (declinfo->storageclass != OBJECT_SCLASS_104) {
+ if (IS_TYPE_FUNC(declinfo->thetype)) {
+ if (!CDecl_FunctionDeclarator(declinfo, NULL, r28, 1))
+ return;
+ } else {
+ CDecl_DataDeclarator(declinfo, ACCESSPUBLIC, 0);
+ }
+ } else {
+ CDecl_TypedefDeclarator(declinfo);
+ }
+
+ CScope_RestoreScope(&savescope);
+ declinfo->thetype = r30;
+ declinfo->qual = r29;
+
+ if (tk != ',')
+ break;
+ tk = lex();
+ r28 = 0;
+ }
+
+ if (tk != ';')
+ CError_Error(123);
+}
+
+static TypeIntegral *CDecl_FindSignedType(short size) {
+ if (stsignedchar.size == size)
+ return &stsignedchar;
+ if (stsignedshort.size == size)
+ return &stsignedshort;
+ if (stsignedint.size == size)
+ return &stsignedint;
+ if (stsignedlong.size == size)
+ return &stsignedlong;
+ if (copts.longlong && copts.longlong_enums && stsignedlonglong.size == size)
+ return &stsignedlonglong;
+ return &stsignedlong;
+}
+
+static TypeIntegral *CDecl_FindUnsignedType(short size) {
+ if (stunsignedchar.size == size)
+ return &stunsignedchar;
+ if (stunsignedshort.size == size)
+ return &stunsignedshort;
+ if (stunsignedint.size == size)
+ return &stunsignedint;
+ if (stunsignedlong.size == size)
+ return &stunsignedlong;
+ if (copts.longlong && copts.longlong_enums && stunsignedlonglong.size == size)
+ return &stunsignedlonglong;
+ return &stunsignedlong;
+}
+
+static TypeIntegral *CDecl_IterateIntegralEnumType(int *t) {
+ switch (*t) {
+ case 0:
+ *t = 1;
+ return &stsignedchar;
+ case 1:
+ if (stsignedshort.size > stsignedchar.size) {
+ *t = 2;
+ return &stsignedshort;
+ }
+ case 2:
+ if (stsignedint.size > stsignedshort.size) {
+ *t = 3;
+ return &stsignedint;
+ }
+ case 3:
+ if (stsignedlong.size > stsignedint.size) {
+ *t = 4;
+ return &stsignedlong;
+ }
+ case 4:
+ *t = 5;
+ if (stsignedlonglong.size > stsignedlong.size && copts.longlong && copts.longlong_enums)
+ return &stsignedlonglong;
+ default:
+ return NULL;
+ }
+}
+
+static TypeIntegral *CDecl_IterateUIntegralEnumType(int *t) {
+ switch (*t) {
+ case 0:
+ *t = 1;
+ return &stunsignedchar;
+ case 1:
+ if (stunsignedshort.size > stunsignedchar.size) {
+ *t = 2;
+ return &stunsignedshort;
+ }
+ case 2:
+ if (stunsignedint.size > stunsignedshort.size) {
+ *t = 3;
+ return &stunsignedint;
+ }
+ case 3:
+ if (stunsignedlong.size > stunsignedint.size) {
+ *t = 4;
+ return &stunsignedlong;
+ }
+ case 4:
+ *t = 5;
+ if (stunsignedlonglong.size > stunsignedlong.size && copts.longlong && copts.longlong_enums)
+ return &stunsignedlonglong;
+ default:
+ return NULL;
+ }
+}
+
+static TypeEnum *CDecl_OldParseEnumList(TypeEnum *tenum, HashNameNode *name) {
+ AccessType access;
+ Boolean has_template_value;
+ Boolean r24;
+ Boolean r23;
+ ObjEnumConst *oec;
+ ObjEnumConst *last;
+ Boolean overflowed;
+ CInt64 val;
+ CInt64 minimum;
+ CInt64 maximum;
+ CInt64 var_74;
+ CInt64 unused;
+ Type *basetype;
+ Type *basetype2;
+ CPrepFileInfo *fileinfo;
+ SInt32 offset;
+ ENode *expr;
+ Type *tmp;
+
+ if (!tenum) {
+ tenum = galloc(sizeof(TypeEnum));
+ memclrw(tenum, sizeof(TypeEnum));
+ tenum->type = TYPEENUM;
+ tenum->nspace = cscope_current;
+
+ if (name) {
+ tenum->enumname = name;
+ CScope_DefineTypeTag(cscope_current, name, TYPE(tenum));
+ }
+
+ if (!cscope_current->is_global) {
+ do {
+ tenum->nspace = tenum->nspace->parent;
+ } while (!tenum->nspace->is_global);
+ if (tenum->enumname)
+ tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name);
+ }
+ }
+
+ if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100)) {
+ CTemplClass_RegisterEnumType(TEMPL_CLASS(cscope_current->theclass), tenum);
+ }
+
+ access = cscope_current->theclass ? global_access : ACCESSPUBLIC;
+ last = NULL;
+ unused = cint64_zero;
+ val = cint64_zero;
+ minimum = cint64_zero;
+ maximum = cint64_zero;
+ r23 = 0;
+ if (copts.enumsalwaysint) {
+ basetype = TYPE(&stsignedint);
+ r24 = 1;
+ } else {
+ basetype = TYPE(&stunsignedchar);
+ r24 = 0;
+ }
+
+ tk = lex();
+ if (!copts.cplusplus || tk != '}') {
+ do {
+ if (tk != TK_IDENTIFIER) {
+ if (tk == '}') {
+ if (copts.cpp_extensions)
+ break;
+ if (!copts.warn_extracomma)
+ break;
+ }
+ CError_Warning(107);
+ break;
+ }
+
+ oec = galloc(sizeof(ObjEnumConst));
+ memclrw(oec, sizeof(ObjEnumConst));
+ oec->otype = OT_ENUMCONST;
+ oec->access = access;
+ oec->type = TYPE(tenum);
+ oec->name = tkidentifier;
+ CPrep_BrowserFilePosition(&fileinfo, &offset);
+ overflowed = 0;
+ if ((tk = lex()) == '=') {
+ tk = lex();
+ val = CExpr_IntegralConstExprType(&basetype2);
+ if (!CInt64_IsNegative(&val) || is_unsigned(basetype2)) {
+ if (CInt64_GreaterU(val, minimum)) {
+ minimum = val;
+ overflowed = 1;
+ }
+ } else {
+ if (CInt64_Less(val, maximum)) {
+ maximum = val;
+ overflowed = 1;
+ }
+ if (!r24) {
+ basetype = TYPE(&stsignedchar);
+ r24 = 1;
+ }
+ }
+ r23 = 0;
+ } else {
+ if (r23)
+ CError_Error(154);
+
+ if (!r24 || !CInt64_IsNegative(&val)) {
+ if (CInt64_GreaterU(val, minimum)) {
+ minimum = val;
+ overflowed = 1;
+ }
+ } else {
+ if (CInt64_Less(val, maximum)) {
+ maximum = val;
+ overflowed = 1;
+ }
+ }
+ }
+
+ if (copts.enumsalwaysint) {
+ if (copts.ANSI_strict) {
+ if (!CInt64_IsInRange(val, stsignedint.size))
+ CError_Error(154);
+ } else {
+ if (!CInt64_IsInRange(val, stsignedint.size) && !CInt64_IsInURange(val, stunsignedint.size))
+ CError_Error(154);
+ }
+ } else if (r24) {
+ switch (basetype->size) {
+ case 1:
+ if (CInt64_IsInRange(minimum, 1) && CInt64_IsInRange(maximum, 1))
+ break;
+ basetype = TYPE(CDecl_FindSignedType(2));
+ case 2:
+ if (CInt64_IsInRange(minimum, 2) && CInt64_IsInRange(maximum, 2))
+ break;
+ basetype = TYPE(CDecl_FindSignedType(4));
+ case 4:
+ if (CInt64_IsInRange(minimum, 4) && CInt64_IsInRange(maximum, 4))
+ break;
+ basetype = TYPE(CDecl_FindSignedType(8));
+ if (basetype->size != 8) {
+ if (!copts.ANSI_strict && CInt64_IsInRange(maximum, 4) && CInt64_IsInURange(minimum, 4))
+ break;
+ if (overflowed)
+ CError_Error(154);
+ break;
+ }
+ case 8:
+ if (CInt64_Equal(val, minimum) && CInt64_IsNegative(&val))
+ CError_Error(154);
+ break;
+ default:
+#line 3071
+ CError_FATAL();
+ }
+ } else {
+ switch (basetype->size) {
+ case 1:
+ if (CInt64_IsInURange(minimum, 1))
+ break;
+ basetype = TYPE(CDecl_FindUnsignedType(2));
+ case 2:
+ if (CInt64_IsInURange(minimum, 2))
+ break;
+ basetype = TYPE(CDecl_FindUnsignedType(4));
+ case 4:
+ if (CInt64_IsInURange(minimum, 4))
+ break;
+ basetype = TYPE(CDecl_FindUnsignedType(8));
+ if (basetype->size != 8) {
+ if (overflowed)
+ CError_Error(154);
+ break;
+ }
+ case 8:
+ break;
+ default:
+#line 3099
+ CError_FATAL();
+ }
+ }
+
+ tenum->size = basetype->size;
+ tenum->enumtype = basetype;
+ oec->val = val;
+ CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec));
+
+ if (last) {
+ last->next = oec;
+ last = oec;
+ } else {
+ last = oec;
+ tenum->enumlist = oec;
+ }
+
+ if (cparamblkptr->browseOptions.recordEnums) {
+ CPrepFileInfo *f = CPrep_BrowserCurrentFile();
+ if (f->recordbrowseinfo) {
+ CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset());
+ }
+ }
+
+ var_74 = CInt64_Add(val, cint64_one);
+ if (r24) {
+ if (CInt64_IsNegative(&var_74) && !CInt64_IsNegative(&val))
+ r23 = 1;
+ } else {
+ if (CInt64_IsZero(&var_74))
+ r23 = 1;
+ }
+ val = var_74;
+
+ if (tk != ',')
+ break;
+ tk = lex();
+ } while (1);
+ }
+
+ tenum->size = basetype->size;
+ tenum->enumtype = basetype;
+
+ for (oec = tenum->enumlist; oec; oec = oec->next)
+ oec->type = TYPE(tenum);
+
+ if (tk != '}')
+ CError_ErrorSkip(130);
+ else
+ tk = lex();
+
+ return tenum;
+}
+
+static Type *CDecl_MaxType(Type *a, Type *b) {
+ if (a->size > b->size)
+ return a;
+ if (b->size > a->size)
+ return b;
+ if (is_unsigned(b))
+ return b;
+ else
+ return a;
+}
+
+void CDecl_ComputeUnderlyingEnumType(TypeEnum *tenum) {
+ ObjEnumConst *oec;
+ ObjEnumConst *oec2;
+ Type *r26;
+ int t;
+ CInt64 maximumU;
+ CInt64 unused;
+ CInt64 minimum, maximum;
+
+ if (!copts.enumsalwaysint) {
+ for (oec2 = tenum->enumlist; oec2; oec2 = oec2->next) {
+ if (CInt64_IsNegative(&oec2->val) && !is_unsigned(oec2->type))
+ break;
+ }
+
+ if (oec2) {
+ unused = cint64_zero;
+ minimum = cint64_zero;
+ maximum = cint64_zero;
+ for (oec = tenum->enumlist; oec; oec = oec->next) {
+ if (CInt64_IsNegative(&oec->val) && !is_unsigned(oec->type)) {
+ if (CInt64_Less(oec->val, minimum))
+ minimum = oec->val;
+ } else {
+ if (CInt64_GreaterU(oec->val, maximum))
+ maximum = oec->val;
+ }
+ }
+
+ if (CInt64_IsNegative(&maximum))
+ CError_Error(154);
+
+ t = 0;
+ do {
+ r26 = TYPE(CDecl_IterateIntegralEnumType(&t));
+ if (!r26) {
+ r26 = TYPE(&stsignedlong);
+ CError_Error(154);
+ break;
+ }
+
+ if (CInt64_IsInRange(maximum, r26->size) && CInt64_IsInRange(minimum, r26->size))
+ break;
+ if (r26->size == stsignedlong.size && !copts.ANSI_strict && CInt64_IsInRange(minimum, r26->size) && CInt64_IsInURange(maximum, r26->size))
+ break;
+ } while (1);
+ } else {
+ maximumU = cint64_zero;
+
+ for (oec = tenum->enumlist; oec; oec = oec->next) {
+ if (CInt64_GreaterU(oec->val, maximumU))
+ maximumU = oec->val;
+ }
+
+ t = 0;
+ do {
+ r26 = TYPE(CDecl_IterateUIntegralEnumType(&t));
+ if (!r26) {
+ r26 = TYPE(&stunsignedlong);
+ CError_Error(154);
+ break;
+ }
+ if (CInt64_IsInURange(maximumU, r26->size))
+ break;
+ } while (1);
+ }
+ } else {
+ r26 = TYPE(&stsignedint);
+ }
+
+ tenum->size = r26->size;
+ tenum->enumtype = r26;
+ for (oec = tenum->enumlist; oec; oec = oec->next)
+ oec->type = TYPE(tenum);
+}
+
+static Type *CDecl_FindUnderlyingType(short size, CInt64 *a, CInt64 *b) {
+ if (CInt64_IsZero(a)) {
+ if (size <= stsignedchar.size && CInt64_IsInURange(*b, stunsignedchar.size))
+ return TYPE(&stunsignedchar);
+ if (size <= stsignedshort.size && CInt64_IsInURange(*b, stunsignedshort.size))
+ return TYPE(&stunsignedshort);
+ if (size <= stsignedint.size && CInt64_IsInURange(*b, stunsignedint.size))
+ return TYPE(&stunsignedint);
+ if (size <= stsignedlong.size && CInt64_IsInURange(*b, stunsignedlong.size))
+ return TYPE(&stunsignedlong);
+ if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInURange(*b, stunsignedlonglong.size))
+ return TYPE(&stunsignedlonglong);
+ } else {
+ if (size <= stsignedchar.size && CInt64_IsInRange(*a, stsignedchar.size) && CInt64_IsInRange(*b, stsignedchar.size))
+ return TYPE(&stsignedchar);
+ if (size <= stsignedshort.size && CInt64_IsInRange(*a, stsignedshort.size) && CInt64_IsInRange(*b, stsignedshort.size))
+ return TYPE(&stsignedshort);
+ if (size <= stsignedint.size && CInt64_IsInRange(*a, stsignedint.size) && CInt64_IsInRange(*b, stsignedint.size))
+ return TYPE(&stsignedint);
+ if (size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInRange(*b, stsignedlong.size))
+ return TYPE(&stsignedlong);
+ if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInRange(*a, stsignedlonglong.size) && CInt64_IsInRange(*b, stsignedlonglong.size))
+ return TYPE(&stsignedlonglong);
+ if (!copts.ANSI_strict && size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInURange(*b, stunsignedlong.size))
+ return TYPE(&stsignedlong);
+ }
+
+ return NULL;
+}
+
+static TypeEnum *CDecl_ParseEnumList(TypeEnum *tenum, HashNameNode *name) {
+ AccessType access;
+ TemplClass *tmclass;
+ ObjEnumConst *oec;
+ Boolean has_template_value;
+ Boolean overflowed;
+ Boolean is_first;
+ CInt64 val;
+ CInt64 minimum;
+ CInt64 maximum;
+ CInt64 unused;
+ Type *basetype;
+ CPrepFileInfo *fileinfo;
+ SInt32 offset;
+ ENode *expr;
+ Type *tmp;
+ ObjEnumConst *last;
+
+ if (!tenum) {
+ tenum = galloc(sizeof(TypeEnum));
+ memclrw(tenum, sizeof(TypeEnum));
+ tenum->type = TYPEENUM;
+ tenum->nspace = cscope_current;
+
+ if (name) {
+ tenum->enumname = name;
+ CScope_DefineTypeTag(cscope_current, name, TYPE(tenum));
+ }
+
+ if (!cscope_current->is_global) {
+ do {
+ tenum->nspace = tenum->nspace->parent;
+ } while (!tenum->nspace->is_global);
+ if (tenum->enumname)
+ tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name);
+ }
+ }
+
+ if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100)) {
+ tmclass = TEMPL_CLASS(cscope_current->theclass);
+ CTemplClass_RegisterEnumType(tmclass, tenum);
+ } else {
+ tmclass = NULL;
+ }
+
+ access = cscope_current->theclass ? global_access : ACCESSPUBLIC;
+ last = NULL;
+ is_first = 1;
+ has_template_value = 0;
+ unused = cint64_zero;
+ val = cint64_zero;
+ minimum = cint64_zero;
+ maximum = cint64_zero;
+ basetype = copts.enumsalwaysint ? TYPE(&stsignedint) : TYPE(&stsignedchar);
+ tenum->size = basetype->size;
+ tenum->enumtype = basetype;
+
+ do {
+ if ((tk = lex()) != TK_IDENTIFIER) {
+ if (tk == '}') {
+ if (is_first) {
+ if (copts.cplusplus)
+ break;
+ } else {
+ if (!copts.warn_extracomma)
+ break;
+ if (copts.c9x)
+ break;
+ if (copts.cpp_extensions)
+ break;
+ }
+ CError_Warning(107);
+ } else {
+ CError_Error(107);
+ }
+ break;
+ }
+
+ oec = galloc(sizeof(ObjEnumConst));
+ memclrw(oec, sizeof(ObjEnumConst));
+ oec->otype = OT_ENUMCONST;
+ oec->access = access;
+ oec->name = tkidentifier;
+ CPrep_BrowserFilePosition(&fileinfo, &offset);
+ overflowed = 0;
+ if ((tk = lex()) == '=') {
+ tk = lex();
+ if (tmclass) {
+ expr = CExpr_IntegralConstOrDepExpr();
+ if (ENODE_IS(expr, EINTCONST)) {
+ val = expr->data.intval;
+ basetype = expr->rtype;
+ has_template_value = 0;
+ } else {
+ val = cint64_zero;
+ basetype = TYPE(tenum);
+ CTemplClass_RegisterEnumerator(tmclass, oec, expr);
+ has_template_value = 1;
+ }
+ } else {
+ val = CExpr_IntegralConstExprType(&basetype);
+ has_template_value = 0;
+ }
+ } else if (has_template_value) {
+ CTemplClass_RegisterEnumerator(tmclass, oec, NULL);
+ } else if (!is_first) {
+ if (is_unsigned(basetype)) {
+ val = CInt64_Add(val, cint64_one);
+ if (CInt64_IsZero(&val))
+ overflowed = 1;
+ } else if (!CInt64_IsNegative(&val)) {
+ val = CInt64_Add(val, cint64_one);
+ if (CInt64_IsNegative(&val))
+ overflowed = 1;
+ } else {
+ val = CInt64_Add(val, cint64_one);
+ }
+ }
+
+ if (!has_template_value) {
+ if (copts.enumsalwaysint) {
+ if (!CInt64_IsInRange(val, stsignedint.size) && (copts.ANSI_strict || !CInt64_IsInURange(val, stunsignedint.size)))
+ overflowed = 1;
+ basetype = TYPE(&stsignedint);
+ } else if (CInt64_IsNegative(&val) && !is_unsigned(basetype)) {
+ if (CInt64_Less(val, minimum)) {
+ minimum = val;
+ if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) {
+ tenum->size = tmp->size;
+ tenum->enumtype = tmp;
+ } else {
+ overflowed = 1;
+ }
+ }
+ } else {
+ if (CInt64_GreaterU(val, maximum)) {
+ maximum = val;
+ if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) {
+ tenum->size = tmp->size;
+ tenum->enumtype = tmp;
+ } else {
+ overflowed = 1;
+ }
+ }
+ }
+ }
+
+ if (overflowed)
+ CError_Error(154);
+
+ oec->val = val;
+ oec->type = basetype;
+ CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec));
+
+ if (last) {
+ last->next = oec;
+ last = oec;
+ } else {
+ last = oec;
+ tenum->enumlist = oec;
+ }
+
+ if (cparamblkptr->browseOptions.recordEnums) {
+ CPrepFileInfo *f = CPrep_BrowserCurrentFile();
+ if (f->recordbrowseinfo) {
+ CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset());
+ }
+ }
+
+ is_first = 0;
+ } while (tk == ',');
+
+ for (oec = tenum->enumlist; oec; oec = oec->next)
+ oec->type = TYPE(tenum);
+
+ if (tk != '}')
+ CError_ErrorSkip(130);
+ else
+ tk = lex();
+
+ return tenum;
+}
+
+void scanenum(DeclInfo *declinfo) {
+ HashNameNode *name;
+ Type *type;
+ CScopeParseResult pr;
+
+ if (tk == '{') {
+ declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL));
+ TYPE_ENUM(declinfo->thetype)->enumname = CParser_AppendUniqueNameFile("@enum");
+ return;
+ }
+
+ if (tk == TK_IDENTIFIER) {
+ name = tkidentifier;
+ if (lookahead() == '{') {
+ type = CScope_GetLocalTagType(cscope_current, name);
+ if (type) {
+ lex();
+ do_shit:
+ if (type->size || !IS_TYPE_ENUM(type)) {
+ CError_Error(122, name->name);
+ declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL));
+ return;
+ }
+ declinfo->thetype = TYPE(CDecl_ParseEnumList(TYPE_ENUM(type), NULL));
+ } else {
+ lex();
+ declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, name));
+ }
+
+ if (cparamblkptr->browseOptions.recordEnums && declinfo->fileoffsetinfo.file->recordbrowseinfo)
+ CBrowse_NewEnum(
+ cscope_current,
+ TYPE_ENUM(declinfo->thetype)->enumname,
+ declinfo->fileoffsetinfo.file,
+ (CPrepFileInfo *) declinfo->fileoffsetinfo.tokenline,
+ declinfo->fileoffsetinfo.tokenoffset,
+ CPrep_BrowserFileOffset());
+ return;
+ } else {
+#line 3851
+ CError_ASSERT(!copts.cplusplus || tk != ';');
+ tkidentifier = name;
+ }
+ }
+
+ if (CScope_ParseElaborateName(&pr)) {
+ if ((type = pr.x8)) {
+ if (!IS_TYPE_ENUM(type))
+ CError_Error(121);
+ if ((tk = lex()) == '{')
+ goto do_shit;
+ declinfo->thetype = type;
+ return;
+ } else {
+#line 3865
+ CError_ASSERT(pr.name_4);
+ if ((tk = lex()) == '{') {
+ declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, pr.name_4));
+ return;
+ } else {
+ CError_Error(140, pr.name_4->name);
+ }
+ }
+ } else {
+ CError_Error(121);
+ }
+
+ declinfo->thetype = TYPE(&stsignedint);
+}
+
+void CDecl_ScanStructDeclarator(BigDeclInfo *bde) {
+ ENode *expr;
+ short val;
+ short bits;
+ Boolean is_bitfield;
+ TypeTemplDep *ttempl;
+ TypeBitfield *tbitfield;
+ Type *type;
+
+ bde->declinfo2 = bde->declinfo;
+ bde->declinfo2.name = NULL;
+ bde->declinfo2.x3E = 0;
+ bde->xCD = 0;
+ is_bitfield = 0;
+
+ if (tk == ':') {
+ bde->declinfo2.name = no_name_node;
+ is_bitfield = 1;
+ } else {
+ bde->declinfo2.x50 = 1;
+ scandeclarator(&bde->declinfo2);
+ if (!bde->declinfo2.name) {
+ CError_Error(131);
+ return;
+ }
+
+ if ((!copts.ANSI_strict || copts.c9x) && !bde->declinfo2.thetype->size && IS_TYPE_ARRAY(bde->declinfo2.thetype)) {
+ if (bde->declinfo2.storageclass != OBJECT_SCLASS_102 && bde->declinfo2.storageclass != OBJECT_SCLASS_104) {
+ type = TYPE_POINTER(bde->declinfo2.thetype)->target;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (!IsCompleteType(type))
+ return;
+ if (tk != ';' || lookahead() != '}') {
+ CError_Error(145);
+ return;
+ }
+ }
+ } else {
+ if (bde->declinfo2.storageclass != OBJECT_SCLASS_102 && bde->declinfo2.storageclass != OBJECT_SCLASS_104) {
+ if (!IS_TYPE_FUNC(bde->declinfo2.thetype) && !IsCompleteType(bde->declinfo2.thetype))
+ return;
+ }
+ }
+
+ if (IS_TYPE_CLASS(bde->declinfo2.thetype) && TYPE_CLASS(bde->declinfo2.thetype)->sominfo) {
+ CError_Error(287);
+ return;
+ }
+
+ if (tk != ':')
+ goto not_a_bitfield;
+ }
+
+ if (!IS_TYPE_INT_OR_ENUM(bde->declinfo2.thetype)) {
+ if (CTemplTool_IsTemplateArgumentDependentType(bde->declinfo2.thetype))
+ goto fuckup;
+ CError_Error(138);
+ bde->declinfo2.thetype = TYPE(&stunsignedint);
+ } else if (copts.ANSI_strict && !copts.cplusplus) {
+ if (bde->declinfo2.thetype != TYPE(&stsignedint) && bde->declinfo2.thetype != TYPE(&stunsignedint)) {
+ CError_Error(138);
+ bde->declinfo2.thetype = TYPE(&stunsignedint);
+ }
+ }
+
+ switch (bde->declinfo2.thetype->size) {
+ case 1:
+ bits = 8;
+ break;
+ case 2:
+ bits = 16;
+ break;
+ case 4:
+ bits = 32;
+ break;
+ default:
+ CError_Error(138);
+ return;
+ }
+fuckup:
+ tk = lex();
+ expr = CExpr_IntegralConstOrDepExpr();
+ if (!ENODE_IS(expr, EINTCONST)) {
+ ttempl = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_BITFIELD));
+ ttempl->u.bitfield.type = bde->declinfo2.thetype;
+ ttempl->u.bitfield.size = CInline_CopyExpression(expr, CopyMode1);
+ bde->declinfo2.thetype = TYPE(ttempl);
+ bde->xCD = 1;
+ return;
+ }
+ val = CInt64_GetULong(&expr->data.intval);
+ if (is_bitfield) {
+ if (val < 0 || val > bits) {
+ CError_Error(138);
+ return;
+ }
+ } else {
+ if (val <= 0 || val > bits) {
+ CError_Error(138);
+ return;
+ }
+ }
+
+ tbitfield = galloc(sizeof(TypeBitfield));
+ memclrw(tbitfield, sizeof(TypeBitfield));
+ tbitfield->type = TYPEBITFIELD;
+ tbitfield->size = bde->declinfo2.thetype->size;
+ tbitfield->bitfieldtype = bde->declinfo2.thetype;
+ tbitfield->unkB = val;
+ bde->declinfo2.thetype = TYPE(tbitfield);
+
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(NULL, &bde->declinfo2);
+
+not_a_bitfield:
+ bde->xCD = 1;
+}
+
+static void CDecl_LayoutStruct(TypeStruct *tstruct) {
+ StructMember *member;
+ SInt32 r28;
+ StructMember *innermember;
+ SInt32 innerbase;
+ StructMember *newmember;
+ StructMember **memberp;
+ TypeBitfield *bf;
+ SInt32 r24;
+ Boolean r23;
+ SInt32 tmp;
+
+ r28 = 0;
+ r23 = 0;
+ CMach_StructLayoutInitOffset(0);
+ for (member = tstruct->members; member; member = member->next) {
+ if (tstruct->stype == STRUCT_TYPE_UNION)
+ CMach_StructLayoutInitOffset(0);
+
+ if (IS_TYPE_BITFIELD(member->type))
+ member->offset = CMach_StructLayoutBitfield(TYPE_BITFIELD(member->type), member->qual);
+ else
+ member->offset = CMach_StructLayoutGetOffset(member->type, member->qual);
+
+ if (tstruct->stype == STRUCT_TYPE_UNION) {
+ tmp = CMach_StructLayoutGetCurSize();
+ if (tmp > r28)
+ r28 = tmp;
+ }
+
+ if (member->name == no_name_node)
+ r23 = 1;
+
+ if (!member->name) {
+#line 4064
+ CError_ASSERT(IS_TYPE_STRUCT(member->type));
+ innerbase = member->offset;
+ innermember = TYPE_STRUCT(member->type)->members;
+ r23 = 1;
+ while (innermember) {
+ if (ismember(tstruct, innermember->name))
+ CError_Error(133, innermember->name->name);
+ if (r23) {
+ member->type = innermember->type;
+ member->name = innermember->name;
+ member->qual = innermember->qual;
+ member->offset = innerbase + innermember->offset;
+ } else {
+ newmember = galloc(sizeof(StructMember));
+ memclrw(newmember, sizeof(StructMember));
+ newmember->next = member->next;
+ newmember->type = innermember->type;
+ newmember->name = innermember->name;
+ newmember->qual = innermember->qual | Q_OVERLOAD;
+ newmember->offset = innerbase + innermember->offset;
+ member->next = newmember;
+ member = newmember;
+ }
+ if (copts.reverse_bitfields && IS_TYPE_BITFIELD(member->type)) {
+ bf = galloc(sizeof(TypeBitfield));
+ *bf = *TYPE_BITFIELD(member->type);
+ CABI_ReverseBitField(bf);
+ member->type = TYPE(bf);
+ }
+ r23 = 0;
+ innermember = innermember->next;
+ }
+ r23 = 1;
+ }
+ }
+
+ if (r23) {
+ memberp = &tstruct->members;
+ while (*memberp) {
+ if ((*memberp)->name == no_name_node || !(*memberp)->name)
+ *memberp = (*memberp)->next;
+ else
+ memberp = &(*memberp)->next;
+ }
+ }
+
+ if (tstruct->stype == STRUCT_TYPE_UNION)
+ r24 = r28;
+ else
+ r24 = CMach_StructLayoutGetCurSize();
+ tstruct->size = r24;
+ tstruct->align = CMach_GetStructAlign(tstruct);
+ tstruct->size = r24 + CABI_StructSizeAlignValue(TYPE(tstruct), r24);
+
+ if (copts.reverse_bitfields) {
+ for (member = tstruct->members; member; member = member->next) {
+ if (IS_TYPE_BITFIELD(member->type))
+ CABI_ReverseBitField(TYPE_BITFIELD(member->type));
+ }
+ }
+
+ if (copts.warn_padding && tstruct->stype != STRUCT_TYPE_UNION) {
+ StructMember *prev;
+
+ member = tstruct->members;
+ prev = NULL;
+ while (member) {
+ if (prev && (prev->offset + prev->type->size) < member->offset) {
+ CError_Warning(350, member->offset - (prev->offset + prev->type->size), prev->name->name);
+ }
+ prev = member;
+ member = member->next;
+ }
+
+ if (prev && (prev->offset + prev->type->size) < tstruct->size) {
+ CError_Warning(350, tstruct->size - (prev->offset + prev->type->size), prev->name->name);
+ }
+ }
+}
+
+static SInt32 scanstructdeclarationlist(TypeStruct *tstruct, Boolean flag) {
+ SInt32 offset;
+ StructMember *member;
+ BigDeclInfo bde;
+
+ offset = -1;
+ memclrw(&bde, sizeof(BigDeclInfo));
+
+ if (tk == TK_AT_DEFS) {
+ CPrep_NewFileOffsetInfo(&member_fileoffset, NULL);
+ CObjC_ParseDefs(tstruct);
+ if ((tk = lex()) != '}')
+ CError_Error(130);
+ } else {
+ do {
+ CPrep_NewFileOffsetInfo(&member_fileoffset, NULL);
+ memclrw(&bde.declinfo, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&bde.declinfo, 0);
+ if (bde.declinfo.storageclass || bde.declinfo.x44) {
+ CError_Error(131);
+ tstruct->members = NULL;
+ return -1;
+ }
+
+ if (tk != ';') {
+ while (1) {
+ CDecl_ScanStructDeclarator(&bde);
+ if (!CanCreateObject(bde.declinfo2.thetype)) {
+ CError_Error(131);
+ bde.xCD = 0;
+ }
+
+ if (bde.declinfo2.x3E) {
+ CError_Error(131);
+ bde.xCD = 0;
+ }
+
+ if (bde.xCD) {
+ if (bde.declinfo2.name == no_name_node || !ismember(tstruct, bde.declinfo2.name)) {
+ member = galloc(sizeof(StructMember));
+ memclrw(member, sizeof(StructMember));
+ member->type = bde.declinfo2.thetype;
+ member->name = bde.declinfo2.name;
+ member->qual = bde.declinfo2.qual;
+ appendmember(tstruct, member);
+
+ if (flag) {
+ CBrowse_AddStructMember(member, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
+ }
+ } else {
+ CError_Error(133, bde.declinfo2.name->name);
+ }
+ }
+
+ if (tk != ',')
+ break;
+ tk = lex();
+ }
+ } else if (!copts.ANSI_strict && IS_TYPE_STRUCT(bde.declinfo.thetype)) {
+ member = galloc(sizeof(StructMember));
+ memclrw(member, sizeof(StructMember));
+ member->type = bde.declinfo.thetype;
+ appendmember(tstruct, member);
+ } else {
+ CError_Error(131);
+ }
+
+ if (tk != ';') {
+ tstruct->members = NULL;
+ CError_Error(123);
+ return -1;
+ }
+
+ CPrep_TokenStreamFlush();
+ } while ((tk = lex()) != '}');
+ CDecl_LayoutStruct(tstruct);
+ }
+
+ if (flag) {
+ offset = CPrep_BrowserFileOffset();
+ if (tk == ';')
+ offset++;
+ }
+
+ tk = lex();
+ return offset;
+}
+
+static TypeStruct *CDecl_DefineStruct(HashNameNode *name, short stype) {
+ TypeStruct *tstruct;
+
+ tstruct = galloc(sizeof(TypeStruct));
+ memclrw(tstruct, sizeof(TypeStruct));
+
+ tstruct->type = TYPESTRUCT;
+ tstruct->align = 1;
+ tstruct->stype = stype;
+ if (name) {
+ tstruct->name = name;
+ CScope_DefineTypeTag((in_func_arglist && !copts.cplusplus) ? cscope_root : cscope_current, name, (Type *) tstruct);
+ }
+
+ return tstruct;
+}
+
+void scanstruct(DeclInfo *declinfo, short structtype) {
+ Type *type;
+ HashNameNode *name;
+ TypeStruct typecopy;
+ Boolean add_to_browse;
+ BrowseStruct bs;
+ SInt32 offset;
+
+ if (copts.cplusplus) {
+ CDecl_ParseClass(declinfo, structtype, 1, 0);
+ return;
+ }
+
+ if (tk == TK_IDENTIFIER) {
+ name = tkidentifier;
+ type = CScope_GetTagType(cscope_current, name);
+ if (type) {
+ if (IS_TYPE_CLASS(type)) {
+ CDecl_ParseClass(declinfo, structtype, 1, 0);
+ return;
+ }
+
+ tk = lex();
+ if (!CScope_GetLocalTagType(cscope_current, name) && (tk == ';' || tk == '{'))
+ type = (Type *) CDecl_DefineStruct(name, structtype);
+
+ if (!IS_TYPE_STRUCT(type) || TYPE_STRUCT(type)->stype != structtype) {
+ CError_Error(132, name->name);
+ declinfo->thetype = type;
+ return;
+ }
+
+ if (tk != '{') {
+ declinfo->thetype = type;
+ return;
+ }
+
+ if (type->size) {
+ CError_Error(132, name->name);
+ type = (Type *) CDecl_DefineStruct(NULL, structtype);
+ }
+ } else {
+ type = (Type *) CDecl_DefineStruct(name, structtype);
+ if ((tk = lex()) != '{') {
+ declinfo->thetype = type;
+ return;
+ }
+ }
+ } else if (tk != '{') {
+ CError_Error(131);
+ declinfo->thetype = (Type *) &stsignedint;
+ return;
+ } else {
+ type = (Type *) CDecl_DefineStruct(NULL, structtype);
+ }
+
+ if ((add_to_browse = cparamblkptr->browseOptions.recordClasses && declinfo->fileoffsetinfo.file->recordbrowseinfo))
+ CBrowse_BeginStruct(declinfo, TYPE_STRUCT(type), &bs);
+
+ typecopy = *TYPE_STRUCT(type);
+ tk = lex();
+ offset = scanstructdeclarationlist(&typecopy, add_to_browse);
+ *TYPE_STRUCT(type) = typecopy;
+ declinfo->thetype = type;
+
+ if (add_to_browse)
+ CBrowse_EndStruct(offset, &bs);
+}
+
+static void InlineFunctionObject(Object *obj, TypeClass *tclass) {
+ TStream stream;
+ CPrepFileInfo *file;
+
+ obj->qual |= Q_INLINE;
+ TYPE_FUNC(obj->type)->flags |= FUNC_FLAGS_2;
+
+ CPrep_StreamGetBlock(&stream, NULL, 1);
+ if (stream.tokens) {
+ if (IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)) && (TYPE_METHOD(obj->type)->theclass->flags & CLASS_FLAGS_100)) {
+ TYPE_FUNC(obj->type)->flags |= FUNC_FLAGS_800000;
+ CTemplClass_DefineMember(TEMPL_CLASS(TYPE_METHOD(obj->type)->theclass), obj, &member_fileoffset, &stream);
+ } else {
+ CInline_AddInlineFunctionAction(obj, tclass, &member_fileoffset, &stream, 0);
+ }
+ }
+
+ file = CPrep_BrowserCurrentFile();
+ if (file->recordbrowseinfo) {
+ CBrowse_NewFunction(
+ obj, file,
+ member_fileoffset.file,
+ CPrep_BrowserTokenOffset(&member_fileoffset) + 1,
+ CPrep_BrowserFileOffset());
+ }
+
+ if (lookahead() == ';')
+ tk = lex();
+ else
+ tk = ';';
+}
+
+void CDecl_ExtractClassExportFlags(DeclInfo *declinfo, UInt8 flags) {
+ if (flags & CLASS_EFLAGS_INTERNAL)
+ declinfo->exportflags |= EXPORT_FLAGS_INTERNAL;
+ if (flags & CLASS_EFLAGS_IMPORT)
+ declinfo->exportflags |= EXPORT_FLAGS_IMPORT;
+ if (flags & CLASS_EFLAGS_EXPORT)
+ declinfo->exportflags |= EXPORT_FLAGS_EXPORT;
+}
+
+TypeMethod *CDecl_MakeTypeMemberFunc(TypeFunc *tfunc, TypeClass *tclass, Boolean flag) {
+ TypeMethod *method;
+
+ method = galloc(sizeof(TypeMethod));
+ memclrw(method, sizeof(TypeMethod));
+ *TYPE_FUNC(method) = *tfunc;
+ method->theclass = tclass;
+ method->x26 = flag;
+ method->flags |= FUNC_FLAGS_METHOD;
+ if (!flag)
+ CDecl_AddThisPointerArgument(TYPE_FUNC(method), tclass);
+
+ if ((flag || (tfunc->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000))) && (tfunc->flags & (FUNC_FLAGS_CONST | FUNC_FLAGS_VOLATILE)))
+ CError_Error(384);
+
+ return method;
+}
+
+static void CDecl_MakeFunctionVirtual(TypeClass *tclass, Object *func) {
+ if (is_pascal_object(func))
+ CError_Error(219);
+ if (tclass->mode == CLASS_MODE_1)
+ CError_Error(352, func);
+ func->datatype = DVFUNC;
+}
+
+static void CDecl_AddFunctionMember(DeclE *decle, TypeClass *tclass, DeclInfo *declinfo, short access, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) {
+ NameSpaceObjectList *list; // r20
+ Object *obj; // also r20
+ TypeMethod *tfunc; // r19
+ Boolean r31;
+ Boolean outflag;
+
+ if (IS_TYPE_ARRAY(TYPE_FUNC(declinfo->thetype)->functype) || IS_TYPE_FUNC(TYPE_FUNC(declinfo->thetype)->functype)) {
+ CError_Error(128);
+ TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint;
+ }
+
+ if (tclass->sominfo)
+ CSOM_CheckFuncType(TYPE_FUNC(declinfo->thetype));
+
+ r31 = 0;
+ if (declinfo->qual & Q_VIRTUAL) {
+ declinfo->qual &= ~Q_VIRTUAL;
+ r31 = 1;
+ flag1 = 1;
+ }
+
+ if ((list = CScope_FindName(tclass->nspace, declinfo->name))) {
+ if (list->object->otype != OT_TYPETAG) {
+ if (list->object->otype != OT_OBJECT || !IS_TYPE_FUNC(OBJECT(list->object)->type))
+ CError_Error(133, declinfo->name->name);
+ } else {
+ list = NULL;
+ }
+ }
+
+ if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype))) {
+ tfunc = CDecl_MakeTypeMemberFunc(TYPE_FUNC(declinfo->thetype), tclass, flag4);
+ declinfo->thetype = (Type *) tfunc;
+ } else {
+ tfunc = TYPE_METHOD(declinfo->thetype);
+#line 4579
+ CError_ASSERT(!tclass->sominfo);
+ }
+
+ CDecl_ExtractClassExportFlags(declinfo, tclass->eflags);
+
+#line 4597
+ CError_ASSERT(cscope_current == tclass->nspace);
+
+ if (list) {
+ obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, flag4 ? OverloadMode1 : OverloadMode2, 0);
+ if (!obj)
+ return;
+ if (outflag)
+ tfunc->x1E = ++decle->x8;
+ else
+ CError_Error(133, CError_GetObjectName(obj));
+ } else {
+ tfunc->x1E = ++decle->x8;
+ obj = CParser_NewFunctionObject(declinfo);
+ if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype))
+ CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(obj));
+ CScope_AddObject(tclass->nspace, declinfo->name, OBJ_BASE(obj));
+ }
+
+ obj->access = access;
+ CheckDefaultArgs(TYPE_FUNC(obj->type)->args);
+
+ if (flag2) {
+ tfunc->flags |= FUNC_FLAGS_40;
+ tclass->flags |= CLASS_FLAGS_40;
+ }
+
+ if (r31) {
+ CDecl_MakeFunctionVirtual(tclass, obj);
+ decle->xC = 1;
+ }
+
+ if ((flag1 || r31) && flag3 && (tk == '=')) {
+ if ((tk = lex()) == TK_INTCONST) {
+ if (!CInt64_IsZero(&tkintconst))
+ CError_Error(121);
+ tfunc->flags |= FUNC_FLAGS_8;
+ tclass->flags |= CLASS_FLAGS_ABSTRACT;
+ tk = lex();
+ } else {
+ CError_Error(121);
+ }
+ }
+
+ if (flag3 && ((tk == '{') || (tk == TK_TRY) || ((tk == ':') && CClass_IsConstructor(obj)))) {
+ if (declinfo->x49)
+ CError_Error(127);
+ InlineFunctionObject(obj, NULL);
+ }
+
+ if (cparamblkptr->browseOptions.recordClasses)
+ CBrowse_AddClassMemberFunction(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
+}
+
+static Boolean CDecl_IsAccessDeclaration(TypeClass *tclass, short access) {
+ SInt32 state;
+ Boolean flag;
+
+ CPrep_TokenStreamGetState(&state);
+ flag = 0;
+
+restart:
+ switch (tk) {
+ case TK_IDENTIFIER:
+ if ((tk = lex()) != ';')
+ break;
+ case TK_OPERATOR:
+ CPrep_TokenStreamSetCurState(&state);
+ if (flag) {
+ CScope_ParseUsingDeclaration(tclass->nspace, access, 1);
+ return 1;
+ }
+ return 0;
+ default:
+ CPrep_TokenStreamSetCurState(&state);
+ return 0;
+ }
+
+ switch (tk) {
+ case TK_COLON_COLON:
+ flag = 1;
+ tk = lex();
+ goto restart;
+ case '<':
+ tk = lex();
+ while (1) {
+ switch (tk) {
+ case 0:
+ case ';':
+ case '{':
+ case '}':
+ CPrep_TokenStreamSetCurState(&state);
+ return 0;
+ case '>':
+ if ((tk = lex()) == TK_COLON_COLON) {
+ flag = 1;
+ tk = lex();
+ goto restart;
+ }
+ default:
+ tk = lex();
+ }
+ }
+ }
+
+ CPrep_TokenStreamSetCurState(&state);
+ return 0;
+}
+
+void CDecl_PackDeclInfo(PackedDeclInfo *packed, DeclInfo *declinfo) {
+ packed->thetype = declinfo->thetype;
+ packed->qual = declinfo->qual;
+ packed->nspace = declinfo->nspace;
+ packed->name = declinfo->name;
+ packed->expltargs = CTemplTool_MakeGlobalTemplArgCopy(declinfo->expltargs);
+ packed->storageclass = declinfo->storageclass;
+ packed->section = declinfo->section;
+ packed->exportflags = declinfo->exportflags;
+ packed->has_expltargs = declinfo->has_expltargs;
+}
+
+void CDecl_UnpackDeclInfo(DeclInfo *declinfo, PackedDeclInfo *packed) {
+ memclrw(declinfo, sizeof(DeclInfo));
+ declinfo->thetype = packed->thetype;
+ declinfo->qual = packed->qual;
+ declinfo->nspace = packed->nspace;
+ declinfo->name = packed->name;
+ declinfo->expltargs = packed->expltargs;
+ declinfo->storageclass = packed->storageclass;
+ declinfo->section = packed->section;
+ declinfo->exportflags = packed->exportflags;
+ declinfo->has_expltargs = packed->has_expltargs;
+}
+
+void CDecl_AddFriend(TypeClass *tclass, Object *friendfunc, TypeClass *friendclass) {
+ ClassFriend *scan;
+ ClassFriend *newfriend;
+
+ if (friendfunc) {
+ for (scan = tclass->friends; scan; scan = scan->next) {
+ if (!scan->isclass && scan->u.obj == friendfunc)
+ break;
+ }
+ if (!scan) {
+ newfriend = galloc(sizeof(ClassFriend));
+ memclrw(newfriend, sizeof(ClassFriend));
+ newfriend->next = tclass->friends;
+ tclass->friends = newfriend;
+ newfriend->u.obj = friendfunc;
+ newfriend->isclass = 0;
+ }
+ }
+
+ if (friendclass) {
+ for (scan = tclass->friends; scan; scan = scan->next) {
+ if (scan->isclass && scan->u.theclass == friendclass)
+ break;
+ }
+ if (!scan) {
+ newfriend = galloc(sizeof(ClassFriend));
+ memclrw(newfriend, sizeof(ClassFriend));
+ newfriend->next = tclass->friends;
+ tclass->friends = newfriend;
+ newfriend->u.theclass = friendclass;
+ newfriend->isclass = 1;
+ }
+ }
+}
+
+static void CDecl_ParseFriendDecl(TypeClass *tclass) {
+ DeclInfo declinfo;
+ DeclInfo declinfo_copy;
+ Boolean is_templ;
+ Boolean r27;
+ Boolean pflag;
+ CScopeSave save;
+ Object *obj;
+ NameSpace *nspace;
+
+ is_templ = (tclass->flags & CLASS_FLAGS_100) ? 1 : 0;
+ r27 = (tk == TK_CLASS || tk == TK_STRUCT || tk == TK_UNION);
+ memclrw(&declinfo, sizeof(DeclInfo));
+
+ declinfo.x4C = 1;
+ CParser_GetDeclSpecs(&declinfo, 1);
+ if (declinfo.storageclass) {
+ CError_Error(177);
+ declinfo.storageclass = 0;
+ }
+ declinfo.x4C = 0;
+
+ if (tk == ';') {
+ if (!r27)
+ CError_Error(201);
+
+ if (IS_TYPE_CLASS(declinfo.thetype)) {
+ if (!(TYPE_CLASS(declinfo.thetype)->flags & CLASS_FLAGS_100) || CParser_CheckTemplateClassUsage(TEMPL_CLASS(declinfo.thetype), 1)) {
+ if (!is_templ)
+ CDecl_AddFriend(tclass, NULL, TYPE_CLASS(declinfo.thetype));
+ else
+ CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo);
+ }
+ } else {
+ if (IS_TYPE_TEMPLATE(declinfo.thetype) && is_templ)
+ CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo);
+ else
+ CError_Error(201);
+ }
+ } else {
+ if (declinfo.x14 || declinfo.x10) {
+ CDecl_ParseSpecialMember(&declinfo, 0);
+ if (declinfo.name) {
+ obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0);
+ if (obj)
+ CDecl_AddFriend(tclass, obj, NULL);
+ if (tk != ';')
+ CError_Error(123);
+ else
+ tk = lex();
+ }
+ return;
+ } else {
+ nspace = CScope_FindGlobalNS(cscope_current);
+ declinfo_copy = declinfo;
+ while (1) {
+ declinfo = declinfo_copy;
+ declinfo.x4D = 1;
+ declinfo.x51 = 1;
+ scandeclarator(&declinfo);
+
+ if (IS_TYPE_FUNC(declinfo.thetype)) {
+ if (!is_templ) {
+ CScope_SetNameSpaceScope(nspace, &save);
+ obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0);
+ CScope_RestoreScope(&save);
+
+ if (obj) {
+ CDecl_AddFriend(tclass, obj, NULL);
+ if (!declinfo.nspace && tk == '{') {
+ InlineFunctionObject(obj, tclass);
+ } else {
+ if (!obj->sclass)
+ obj->sclass = OBJECT_SCLASS_103;
+ }
+ }
+ } else {
+ CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo);
+ }
+ } else {
+ CError_Error(201);
+ }
+
+ if (tk != ',')
+ break;
+ tk = lex();
+ }
+ }
+ }
+
+ if (tk == ';')
+ tk = lex();
+ else
+ CError_Error(123);
+}
+
+static ObjMemberVar *CDecl_InstanceDataDeclarator(DeclE *decle, TypeClass *tclass, Type *type, UInt32 qual, HashNameNode *name, short access) {
+ NameSpaceObjectList *list;
+ ObjMemberVar *ivar;
+ ObjMemberVar *scan;
+
+ if (name && (list = CScope_FindName(tclass->nspace, name))) {
+ switch (list->object->otype) {
+ case OT_NAMESPACE:
+ CError_Error(321);
+ return NULL;
+ case OT_ENUMCONST:
+ case OT_TYPE:
+ case OT_OBJECT:
+ CError_Error(322);
+ return NULL;
+ case OT_MEMBERVAR:
+ CError_Error(122, name->name);
+ return NULL;
+ case OT_TYPETAG:
+ break;
+ default:
+#line 4989
+ CError_FATAL();
+ }
+ }
+
+ ivar = galloc(sizeof(ObjMemberVar));
+ memclrw(ivar, sizeof(ObjMemberVar));
+ ivar->otype = OT_MEMBERVAR;
+ ivar->access = access;
+ ivar->name = name;
+ ivar->type = type;
+ ivar->qual = qual;
+ if (!tclass->sominfo)
+ decle->x8++;
+
+ if ((scan = tclass->ivars)) {
+ while (scan->next)
+ scan = scan->next;
+ scan->next = ivar;
+ } else {
+ tclass->ivars = ivar;
+ }
+
+ if (name && name != no_name_node) {
+ CScope_AddObject(tclass->nspace, name, OBJ_BASE(ivar));
+ if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(type))
+ CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(ivar));
+ if (cparamblkptr->browseOptions.recordClasses)
+ CBrowse_AddClassMemberVar(ivar, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset());
+ }
+
+ return ivar;
+}
+
+void CDecl_CheckCtorIntegrity(FuncArg *args, TypeClass *tclass) {
+ if (args && args->type == TYPE(tclass)) {
+ if (!args->next || args->next->dexpr) {
+ CError_Error(239);
+ args->type = &stvoid;
+ }
+ }
+}
+
+static void CDecl_ParseClassMembers(DeclE *decle, TypeClass *tclass, short mode) {
+ short access;
+ UInt32 r22;
+ UInt32 r21;
+ UInt8 r20;
+ Boolean r19;
+ UInt8 r18;
+ Boolean r17;
+ BigDeclInfo bde;
+ DeclInfo declinfo;
+ //Type *newtype
+ ObjMemberVar *ivar;
+ ObjMemberVar *scanivar;
+ Type *tmptype;
+ short t;
+
+ r17 = (tclass->flags & CLASS_FLAGS_100) && TEMPL_CLASS(tclass)->pspec_owner;
+ memclrw(&bde, sizeof(BigDeclInfo));
+
+ if (mode == CLASS_MODE_2)
+ access = ACCESSPRIVATE;
+ else
+ access = ACCESSPUBLIC;
+ global_access = access;
+ //global_access = (mode == CLASS_MODE_2) ? ACCESSPRIVATE : ACCESSPUBLIC;
+ //access = (mode == CLASS_MODE_2) ? ACCESSPRIVATE : ACCESSPUBLIC;
+
+ restart:
+ while (tk != '}') {
+ CPrep_NewFileOffsetInfo(&member_fileoffset, NULL);
+ r21 = 0;
+ r22 = 0;
+ r20 = 0;
+ r18 = 0;
+
+ if (tk == TK_TEMPLATE) {
+ NameSpace *nspace = cscope_current;
+ TemplClass *tmclass;
+
+ if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)) {
+ tmclass = TEMPL_CLASS(nspace->theclass);
+ } else {
+ for (; nspace; nspace = nspace->parent) {
+ if (!nspace->name && !nspace->theclass && nspace->parent && !nspace->is_templ) {
+ CError_Error(347);
+ break;
+ }
+ }
+ }
+
+ CTempl_Parse(tclass, access);
+ tk = lex();
+ continue;
+ }
+
+ restart2:
+ r19 = 0;
+ switch (tk) {
+ case TK_UU_DECLSPEC:
+ if ((tk = lex()) != '(')
+ CError_Error(114);
+ memclrw(&declinfo, sizeof(DeclInfo));
+ CParser_ParseDeclSpec(&declinfo, 1);
+ r21 |= declinfo.qual;
+ r20 |= declinfo.exportflags;
+ r18 = declinfo.section;
+ if ((tk = lex()) != ')')
+ CError_Error(115);
+ tk = lex();
+ goto restart2;
+ case TK_PRIVATE:
+ global_access = access = ACCESSPRIVATE;
+ goto check_access;
+ case TK_PROTECTED:
+ global_access = access = ACCESSPROTECTED;
+ goto check_access;
+ case TK_PUBLIC:
+ global_access = access = ACCESSPUBLIC;
+ check_access:
+ if (r22 || r20)
+ CError_Error(121);
+ if ((tk = lex()) != ':')
+ CError_Error(170);
+ else
+ tk = lex();
+ goto restart;
+ case TK_EXPLICIT:
+ CError_QualifierCheck(r22 & Q_EXPLICIT);
+ r22 |= Q_EXPLICIT;
+ tk = lex();
+ goto restart2;
+ case TK_INLINE:
+ CError_QualifierCheck(r22 & Q_INLINE);
+ r22 |= Q_INLINE;
+ tk = lex();
+ goto restart2;
+ case TK_ASM:
+ CError_QualifierCheck(r22 & Q_ASM);
+ r22 |= Q_ASM;
+ tk = lex();
+ goto restart2;
+ case TK_VIRTUAL:
+ CError_QualifierCheck(r22 & Q_VIRTUAL);
+ r22 |= Q_VIRTUAL;
+ tk = lex();
+ goto restart2;
+ case TK_IDENTIFIER:
+ while (1) {
+ if (tkidentifier == tclass->classname) {
+ t = lookahead();
+ tkidentifier = tclass->classname;
+ r19 = 1;
+ if (copts.cpp_extensions && t == TK_COLON_COLON) {
+ lex();
+ tk = lex();
+ if (tk == TK_IDENTIFIER)
+ continue;
+ if (tk == '~')
+ goto restart2;
+ CError_Error(107);
+ }
+
+ if (t == '(') {
+ redo_thing:
+ CError_QualifierCheck(r22 & ~(Q_EXPLICIT | Q_INLINE | Q_ASM));
+ memclrw(&bde.declinfo2, sizeof(DeclInfo));
+ if (tclass->sominfo)
+ bde.declinfo2.thetype = &stvoid;
+ else
+ bde.declinfo2.thetype = TYPE(&void_ptr);
+
+ bde.declinfo2.qual = r22;
+ bde.declinfo2.exportflags = r20;
+ bde.declinfo2.section = r18;
+ bde.declinfo2.x4B = 1;
+ scandeclarator(&bde.declinfo2);
+ if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
+ if (r17)
+ bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(tclass, bde.declinfo2.thetype, &bde.declinfo2.qual);
+ if (tclass->sominfo) {
+ if (TYPE_FUNC(bde.declinfo2.thetype)->args)
+ CError_Error(272);
+ bde.declinfo2.qual |= Q_VIRTUAL;
+ } else {
+ CDecl_CheckCtorIntegrity(TYPE_FUNC(bde.declinfo2.thetype)->args, tclass);
+ if (tclass->flags & CLASS_FLAGS_20)
+ CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort));
+ bde.declinfo2.qual &= ~Q_VIRTUAL;
+ }
+ TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_FLAGS_1000;
+ bde.declinfo2.name = constructor_name_node;
+ bde.declinfo2.qual |= r21;
+ CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 0);
+ } else {
+ CError_Error(241);
+ }
+ if (tk == ';')
+ tk = lex();
+ else
+ CError_Error(123);
+ goto restart;
+ }
+ }
+ // 6F8D8
+ if (!r22 && CDecl_IsAccessDeclaration(tclass, access)) {
+ tk = lex();
+ goto restart;
+ }
+ break;
+ }
+ break;
+ case TK_USING:
+ CError_QualifierCheck(r22);
+ tk = lex();
+ CScope_ParseUsingDeclaration(tclass->nspace, access, 0);
+ tk = lex();
+ goto restart;
+ case '~':
+ if ((tk = lex()) != TK_IDENTIFIER || tkidentifier != tclass->classname) {
+ CError_Error(241);
+ goto restart;
+ }
+ CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM));
+ if (tclass->flags & CLASS_FLAGS_900) {
+ t = lookahead();
+ tkidentifier = tclass->classname;
+ if (t == '<') {
+ memclrw(&bde.declinfo, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&bde.declinfo, 0);
+ if (tk != '(' || bde.declinfo.thetype != TYPE(tclass) || bde.declinfo.nspace) {
+ CError_Error(241);
+ goto restart;
+ }
+ CPrep_UnLex();
+ tk = TK_IDENTIFIER;
+ tkidentifier = tclass->classname;
+ }
+ }
+ memclrw(&bde.declinfo2, sizeof(DeclInfo));
+ bde.declinfo2.qual = r22;
+ bde.declinfo2.exportflags = r20;
+ bde.declinfo2.section = r18;
+ if (tclass->sominfo)
+ bde.declinfo2.thetype = &stvoid;
+ else
+ bde.declinfo2.thetype = TYPE(&void_ptr);
+ scandeclarator(&bde.declinfo2);
+ if (IS_TYPE_FUNC(bde.declinfo2.thetype) && !TYPE_FUNC(bde.declinfo2.thetype)->args) {
+ if (!CScope_FindName(tclass->nspace, destructor_name_node)) {
+ if (tclass->sominfo)
+ bde.declinfo2.qual |= Q_VIRTUAL;
+ else
+ CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort));
+ bde.declinfo2.name = destructor_name_node;
+ TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_FLAGS_2000;
+ bde.declinfo2.qual |= r21;
+ CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0);
+ } else {
+ CError_Error(133, CError_GetFunctionName(tclass->nspace, destructor_name_node, NULL));
+ }
+ } else {
+ CError_Error(146);
+ }
+ if (tk == ';')
+ tk = lex();
+ else
+ CError_Error(123);
+ goto restart;
+ case TK_OPERATOR:
+ if (CMangler_OperatorName(lookahead())) {
+ memclrw(&bde.declinfo, sizeof(DeclInfo));
+ bde.declinfo.thetype = TYPE(&stsignedint);
+ goto after_various_things;
+ } else {
+ tk = lex();
+ CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM));
+ memclrw(&bde.declinfo2, sizeof(DeclInfo));
+ bde.declinfo2.qual = r22;
+ bde.declinfo2.exportflags = r20;
+ bde.declinfo2.section = r18;
+ conversion_type_name(&bde.declinfo2);
+ bde.declinfo2.qual |= r21;
+ tmptype = bde.declinfo2.thetype;
+ CDecl_NewConvFuncType(&bde.declinfo2);
+ if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(tmptype))
+ bde.declinfo2.name = CParser_GetUniqueName();
+ CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 1, 1, 0);
+ if (tk == ';')
+ tk = lex();
+ else
+ CError_Error(123);
+ goto restart;
+ }
+ case TK_FRIEND:
+ tk = lex();
+ CDecl_ParseFriendDecl(tclass);
+ goto restart;
+ }
+
+ CError_QualifierCheck(r22 & Q_EXPLICIT);
+ global_access = access;
+ memclrw(&bde.declinfo, sizeof(DeclInfo));
+ bde.declinfo.qual = r22;
+ bde.declinfo.exportflags = r20;
+ bde.declinfo.section = r18;
+ CParser_GetDeclSpecs(&bde.declinfo, 0);
+
+ if (r19 && tk == '(' && (tclass->flags & CLASS_FLAGS_900) && bde.declinfo.thetype == TYPE(tclass) && !bde.declinfo.nspace) {
+ CPrep_UnLex();
+ tk = TK_IDENTIFIER;
+ tkidentifier = tclass->classname;
+ r22 = bde.declinfo.qual;
+ goto redo_thing;
+ }
+
+ after_various_things:
+ switch (bde.declinfo.storageclass) {
+ case 0:
+ case OBJECT_SCLASS_102:
+ case OBJECT_SCLASS_104:
+ case OBJECT_SCLASS_12B:
+ break;
+ default:
+ CError_Error(177);
+ bde.declinfo.storageclass = 0;
+ }
+
+ if (tk != ';') {
+ while (1) {
+ CDecl_ScanStructDeclarator(&bde);
+ if (r17)
+ bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(tclass, bde.declinfo2.thetype, &bde.declinfo2.qual);
+ if (bde.declinfo2.nspace)
+ CError_Error(200);
+ if (bde.declinfo2.x3E) {
+ if (bde.declinfo.storageclass == OBJECT_SCLASS_12B)
+ CError_QualifierCheck(Q_MUTABLE);
+ r19 = 0;
+ switch (bde.declinfo2.x3E) {
+ case TK_NEW:
+ case TK_NEW_ARRAY:
+ CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
+ r19 = 1;
+ break;
+ case TK_DELETE:
+ case TK_DELETE_ARRAY:
+ CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
+ r19 = 1;
+ break;
+ default:
+ if (bde.declinfo2.storageclass == OBJECT_SCLASS_102)
+ CError_Error(193);
+ if (tclass->sominfo)
+ CError_Error(193);
+ }
+
+ bde.declinfo2.storageclass = 0;
+ if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
+ bde.declinfo2.qual |= r21;
+ CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, r19 == 0, 0, 1, r19);
+ CDecl_CheckOperatorType(&bde.declinfo2, 1);
+ if (tclass->sominfo)
+ CSOM_FixNewDeleteFunctype(TYPE_FUNC(bde.declinfo2.thetype));
+ } else {
+ CError_Error(121);
+ }
+ } else if (bde.xCD) {
+ if (bde.declinfo2.name == constructor_name_node || bde.declinfo2.name == destructor_name_node)
+ CError_Error(241);
+ switch (bde.declinfo2.storageclass) {
+ case OBJECT_SCLASS_104:
+ CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
+ CDecl_TypedefDeclarator(&bde.declinfo2);
+ break;
+ case OBJECT_SCLASS_102:
+ CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL);
+ if (tclass->sominfo)
+ CError_Error(271);
+ if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
+ bde.declinfo2.qual |= r21;
+ bde.declinfo2.storageclass = 0;
+ if (bde.declinfo2.name == tclass->classname)
+ CError_Error(241);
+ CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 1);
+ } else {
+ CDecl_ExtractClassExportFlags(&bde.declinfo2, tclass->eflags);
+ bde.declinfo2.storageclass = 0;
+ CDecl_DataDeclarator(&bde.declinfo2, access, 1);
+ }
+ break;
+ case 0:
+ case OBJECT_SCLASS_12B:
+ if (IS_TYPE_FUNC(bde.declinfo2.thetype)) {
+ if (bde.declinfo2.name == tclass->classname)
+ CError_Error(241);
+ if (bde.declinfo.storageclass == OBJECT_SCLASS_12B)
+ CError_QualifierCheck(Q_MUTABLE);
+ bde.declinfo2.qual |= r21;
+ CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0);
+ } else {
+ CDecl_CompleteType(bde.declinfo2.thetype);
+ CanCreateObject(bde.declinfo2.thetype);
+ CError_QualifierCheck(bde.declinfo2.qual & (Q_VIRTUAL | Q_INLINE));
+ if (bde.declinfo2.storageclass == OBJECT_SCLASS_12B)
+ bde.declinfo2.qual |= Q_MUTABLE;
+ CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo2.thetype, bde.declinfo2.qual, bde.declinfo2.name, access);
+ }
+ break;
+ default:
+ CError_Error(177);
+ }
+ }
+
+ // this should be 70058
+ if (tk != ',')
+ break; // goes to 70148
+ tk = lex();
+ }
+ } else if (CParser_IsAnonymousUnion(&bde.declinfo, 1)) {
+ if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo.thetype, 0, NULL, access)))
+ ivar->anonunion = 1;
+ for (scanivar = TYPE_CLASS(bde.declinfo.thetype)->ivars; scanivar; scanivar = scanivar->next) {
+ tmptype = scanivar->type;
+ if (IS_TYPE_BITFIELD(tmptype) && copts.reverse_bitfields) {
+ TypeBitfield *newtype = galloc(sizeof(TypeBitfield));
+ *newtype = *TYPE_BITFIELD(tmptype);
+ CABI_ReverseBitField(newtype);
+ tmptype = TYPE(newtype);
+ }
+ if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, tmptype, scanivar->qual, scanivar->name, access)))
+ ivar->offset = scanivar->offset | 0x80000000;
+ }
+ }
+
+ // this should be 70148 i think
+ if (tk != ';') {
+ CError_Error(123);
+ return;
+ }
+ CPrep_TokenStreamFlush();
+ tk = lex();
+ }
+}
+
+static VClassList *AddVBaseToList(TypeClass *tclass, TypeClass *baseclass) {
+ VClassList *scan;
+ VClassList *vbase;
+
+ for (scan = tclass->vbases; scan; scan = scan->next) {
+ if (scan->base == baseclass)
+ return NULL;
+ }
+
+ vbase = galloc(sizeof(VClassList));
+ memclrw(vbase, sizeof(VClassList));
+ vbase->base = baseclass;
+
+ if ((scan = tclass->vbases)) {
+ while (scan->next)
+ scan = scan->next;
+ scan->next = vbase;
+ } else {
+ tclass->vbases = vbase;
+ }
+
+ return vbase;
+}
+
+void CDecl_MakeVBaseList(TypeClass *tclass) {
+ ClassList *base;
+ VClassList *vbase;
+ VClassList *new_vbase;
+ SInt32 offset;
+
+ if (copts.vbase_ctor_offset)
+ tclass->flags |= CLASS_FLAGS_8000;
+
+ for (base = tclass->bases, offset = tclass->size; base; base = base->next) {
+ for (vbase = base->base->vbases; vbase; vbase = vbase->next) {
+ if ((new_vbase = AddVBaseToList(tclass, vbase->base))) {
+ new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(vbase->base), offset);
+ offset = new_vbase->offset + vbase->base->size;
+ }
+ }
+
+ if (base->is_virtual && (new_vbase = AddVBaseToList(tclass, base->base))) {
+ new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(base->base), offset);
+ offset = new_vbase->offset + base->base->size;
+ }
+ }
+}
+
+Boolean CDecl_CheckNewBase(TypeClass *tclass, TypeClass *baseclass, Boolean is_virtual) {
+ ClassList *scan;
+
+ if (tclass == baseclass) {
+ CError_Error(131);
+ return 0;
+ }
+
+ if (!(baseclass->flags & CLASS_FLAGS_2)) {
+ CError_Error(136, baseclass, 0);
+ return 0;
+ }
+
+ if (baseclass->flags & CLASS_FLAGS_10) {
+ if (is_virtual || tclass->bases) {
+ CError_Error(191);
+ return 0;
+ }
+ tclass->flags |= CLASS_FLAGS_10;
+ }
+
+ if (baseclass->flags & CLASS_FLAGS_1) {
+ if (is_virtual || tclass->bases) {
+ CError_Error(191);
+ return 0;
+ }
+ tclass->flags |= CLASS_FLAGS_1;
+ }
+
+ if (baseclass->sominfo) {
+ if (!is_virtual)
+ CError_Error(268);
+ CSOM_MakeSOMClass(tclass);
+ } else if (tclass->sominfo) {
+ CError_Error(267);
+ }
+
+ if (tclass->bases && (tclass->flags & CLASS_FLAGS_10) && (tclass->flags & CLASS_FLAGS_10)) {
+ CError_Error(131);
+ return 0;
+ }
+
+ if (copts.ecplusplus && (is_virtual || tclass->bases)) {
+ CError_Error(339);
+ return 0;
+ }
+
+ for (scan = tclass->bases; scan; scan = scan->next) {
+ if (scan->base == baseclass) {
+ CError_Error(131);
+ return 0;
+ }
+ }
+
+ if (baseclass->flags & CLASS_FLAGS_2000)
+ tclass->flags |= CLASS_FLAGS_2000;
+ if (baseclass->flags & CLASS_FLAGS_40)
+ tclass->flags |= CLASS_FLAGS_40;
+ if (baseclass->flags & CLASS_FLAGS_20)
+ tclass->flags |= CLASS_FLAGS_20;
+
+ if (is_virtual)
+ tclass->flags |= CLASS_FLAGS_20;
+
+ return 1;
+}
+
+static void CDecl_ParseBaseClassList(TypeClass *tclass, short mode, Boolean is_templ) {
+ Boolean is_virtual;
+ short access;
+ CScopeParseResult pr;
+ ObjType *inherited_type;
+ ClassList *base;
+ ClassList *scan;
+ TypeClass *baseclass;
+
+ do {
+ if (mode == CLASS_MODE_2)
+ access = ACCESSPRIVATE;
+ else
+ access = ACCESSPUBLIC;
+
+ is_virtual = 0;
+ if ((tk = lex()) == TK_VIRTUAL) {
+ tk = lex();
+ is_virtual = 1;
+ }
+
+ switch (tk) {
+ case TK_PRIVATE:
+ access = ACCESSPRIVATE;
+ tk = lex();
+ break;
+ case TK_PUBLIC:
+ access = ACCESSPUBLIC;
+ tk = lex();
+ break;
+ case TK_PROTECTED:
+ if (!copts.ARM_conform) {
+ access = ACCESSPROTECTED;
+ tk = lex();
+ }
+ break;
+ }
+
+ if (tk == TK_VIRTUAL) {
+ if (is_virtual)
+ CError_Error(121);
+ is_virtual = 1;
+ tk = lex();
+ }
+
+ if (CScope_ParseDeclName(&pr)) {
+ if (!pr.x8) {
+ if (!pr.name_4) {
+ CError_Error(121);
+ } else if (tk == TK_IDENTIFIER && pr.name_4 == tkidentifier) {
+ goto special_parsing;
+ }
+ CError_Error(140, tkidentifier->name);
+ continue;
+ }
+
+ CDecl_CompleteType(pr.x8);
+ if (is_templ && CTemplTool_IsTemplateArgumentDependentType(pr.x8)) {
+ if (!IS_TYPE_CLASS(pr.x8) || !(TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100) ||
+ CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.x8), 1)) {
+ CTemplClass_RegisterBaseClass(TEMPL_CLASS(tclass), pr.x8, access, is_virtual);
+ if (is_virtual)
+ tclass->flags |= CLASS_FLAGS_20;
+ }
+ continue;
+ }
+
+ if (!IS_TYPE_CLASS(pr.x8) || (TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100)) {
+ CError_Error(131);
+ continue;
+ }
+ baseclass = TYPE_CLASS(pr.x8);
+ } else {
+ special_parsing:
+ if (!strcmp(tkidentifier->name, "HandleObject")) {
+ if (tclass->bases)
+ CError_Error(191);
+ tclass->flags |= CLASS_FLAGS_10 | CLASS_FLAGS_1;
+ tk = lex();
+ break;
+ }
+ if (!strcmp(tkidentifier->name, "SingleObject") || !strcmp(tkidentifier->name, "SingleInheritance")) {
+ if (tclass->bases)
+ CError_Error(191);
+ tclass->flags |= CLASS_FLAGS_10;
+ tk = lex();
+ break;
+ }
+ if (!strcmp(tkidentifier->name, "__comobject")) {
+ tclass->flags |= CLASS_FLAGS_2000;
+ tk = lex();
+ break;
+ }
+ if (!strcmp(tkidentifier->name, "__somobject")) {
+ if (!is_virtual)
+ CError_Error(268);
+ CSOM_MakeSOMClass(tclass);
+ tk = lex();
+ break;
+ }
+ if (!strcmp(tkidentifier->name, "__javaobject")) {
+ tk = lex();
+ tclass->action = CLASS_ACTION_3;
+ break;
+ }
+
+ CError_Error(140, tkidentifier->name);
+ continue;
+ }
+
+ if (CDecl_CheckNewBase(tclass, baseclass, is_virtual)) {
+ base = galloc(sizeof(ClassList));
+ memclrw(base, sizeof(ClassList));
+ base->base = baseclass;
+ base->access = access;
+ base->is_virtual = is_virtual;
+ if ((scan = tclass->bases)) {
+ while (scan->next)
+ scan = scan->next;
+ scan->next = base;
+ } else {
+ tclass->bases = base;
+ }
+ }
+ } while ((tk = lex()) == ',');
+
+ if (tclass->flags & CLASS_FLAGS_20)
+ CDecl_MakeVBaseList(tclass);
+
+ if (copts.def_inherited && tclass->bases && !tclass->bases->next) {
+ inherited_type = galloc(sizeof(ObjType));
+ memclrw(inherited_type, sizeof(ObjType));
+ inherited_type->otype = OT_TYPE;
+ inherited_type->access = ACCESSPUBLIC;
+ inherited_type->type = TYPE(tclass->bases->base);
+ CScope_AddObject(tclass->nspace, GetHashNameNodeExport("inherited"), OBJ_BASE(inherited_type));
+ }
+}
+
+static short getaccesstype(short a, short b, short c) {
+ AccessType a1 = (AccessType) a;
+ AccessType b1 = (AccessType) b;
+ AccessType c1 = (AccessType) c;
+
+ if (a1 == ACCESSNONE || b1 == ACCESSNONE || b1 == ACCESSPRIVATE)
+ return ACCESSNONE;
+ else if (c1 == ACCESSPUBLIC && a1 != ACCESSPUBLIC)
+ return ACCESSNONE;
+ else
+ return ACCESSPUBLIC;
+}
+
+static TypeMethod *CDecl_MakeDefaultCtorType(TypeClass *tclass) {
+ TypeMethod *tmeth = galloc(sizeof(TypeMethod));
+ memclrw(tmeth, sizeof(TypeMethod));
+ tmeth->type = TYPEFUNC;
+ tmeth->functype = TYPE(&void_ptr);
+ tmeth->flags = FUNC_FLAGS_1000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
+ tmeth->theclass = tclass;
+ CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
+
+ if (tclass->flags & CLASS_FLAGS_20)
+ CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort));
+
+ CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
+ return tmeth;
+}
+
+static void CDecl_AddDefArgConstructor(TypeClass *tclass) {
+ // empty
+}
+
+static void CDecl_AddMemberFunctionObject(TypeClass *tclass, HashNameNode *name, TypeMethod *tmeth, short access) {
+ Object *obj = CParser_NewCompilerDefFunctionObject();
+ obj->name = name;
+ obj->type = TYPE(tmeth);
+ obj->qual = Q_80000;
+ obj->access = access;
+ obj->nspace = tclass->nspace;
+ obj->qual |= Q_INLINE;
+ CScope_AddObject(tclass->nspace, obj->name, OBJ_BASE(obj));
+}
+
+static void CDecl_AddDefaultConstructor(DeclE *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjMemberVar *ivar;
+ Object *obj;
+ Boolean has_ctor;
+
+ if (CClass_Constructor(tclass)) {
+ CDecl_AddDefArgConstructor(tclass);
+ return;
+ }
+
+ has_ctor = 0;
+
+ if (tclass->flags & CLASS_FLAGS_20)
+ has_ctor = 1;
+ if (decle->xC)
+ has_ctor = 1;
+
+ for (base = tclass->bases; base; base = base->next) {
+ if (CClass_Constructor(base->base))
+ has_ctor = 1;
+ }
+
+ for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
+ Type *type = ivar->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type)))
+ has_ctor = 1;
+ }
+
+ if (has_ctor) {
+ CDecl_AddMemberFunctionObject(
+ tclass,
+ constructor_name_node,
+ CDecl_MakeDefaultCtorType(tclass),
+ ACCESSPUBLIC
+ );
+ }
+}
+
+static TypeMethod *CDecl_MakeCopyCtorType(TypeClass *tclass, Boolean is_const) {
+ FuncArg *arg;
+ TypeMethod *tmeth = galloc(sizeof(TypeMethod));
+ memclrw(tmeth, sizeof(TypeMethod));
+ tmeth->type = TYPEFUNC;
+ tmeth->functype = TYPE(&void_ptr);
+ tmeth->flags = FUNC_FLAGS_1000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
+ tmeth->theclass = tclass;
+ CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
+
+ arg = CParser_NewFuncArg();
+ if (is_const)
+ arg->qual = Q_CONST;
+ arg->type = CDecl_NewRefPointerType(TYPE(tclass));
+ tmeth->args = arg;
+
+ if (tclass->flags & CLASS_FLAGS_20)
+ CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort));
+
+ CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
+ return tmeth;
+}
+
+static void CDecl_AddDefaultCopyConstructor(DeclE *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjMemberVar *ivar;
+ Object *obj;
+ short access;
+ Boolean has_copyctor;
+ Boolean is_const;
+ FuncArg *arg;
+
+ if (CClass_CopyConstructor(tclass))
+ return;
+
+ access = ACCESSPUBLIC;
+ is_const = 1;
+ has_copyctor = 0;
+
+ if (CClass_Constructor(tclass))
+ has_copyctor = 1;
+ if ((tclass->flags & CLASS_FLAGS_20) || decle->xC)
+ has_copyctor = 1;
+
+ for (base = tclass->bases; base; base = base->next) {
+ if ((obj = CClass_CopyConstructor(base->base))) {
+ has_copyctor = 1;
+ access = getaccesstype(access, obj->access, ACCESSPRIVATE);
+ arg = TYPE_FUNC(obj->type)->args->next;
+ if (base->base->flags & CLASS_FLAGS_20)
+ arg = arg->next;
+ if (!(arg->qual & Q_CONST))
+ is_const = 0;
+ }
+ }
+
+ for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
+ Type *type = ivar->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (IS_TYPE_CLASS(type) && (obj = CClass_CopyConstructor(TYPE_CLASS(type)))) {
+ has_copyctor = 1;
+ access = getaccesstype(access, obj->access, ACCESSPUBLIC);
+ arg = TYPE_FUNC(obj->type)->args->next;
+ if (TYPE_CLASS(type)->flags & CLASS_FLAGS_20)
+ arg = arg->next;
+ if (!(arg->qual & Q_CONST))
+ is_const = 0;
+ }
+ }
+
+ if (has_copyctor) {
+ CDecl_AddMemberFunctionObject(
+ tclass,
+ constructor_name_node,
+ CDecl_MakeCopyCtorType(tclass, is_const),
+ access
+ );
+ }
+}
+
+static TypeMethod *CDecl_MakeAssignmentOperatorType(TypeClass *tclass, Boolean is_const) {
+ FuncArg *arg;
+ TypeMethod *tmeth = galloc(sizeof(TypeMethod));
+ memclrw(tmeth, sizeof(TypeMethod));
+ tmeth->type = TYPEFUNC;
+ tmeth->functype = CDecl_NewRefPointerType(TYPE(tclass));
+ tmeth->flags = FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
+ tmeth->theclass = tclass;
+ CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
+
+ arg = CParser_NewFuncArg();
+ if (is_const)
+ arg->qual = Q_CONST;
+ arg->type = CDecl_NewRefPointerType(TYPE(tclass));
+ tmeth->args = arg;
+
+ CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
+ return tmeth;
+}
+
+static void CDecl_AddDefaultAssignmentOperator(DeclE *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjMemberVar *ivar;
+ Object *obj;
+ short access;
+ Boolean is_const;
+ Boolean has_ass;
+ DeclInfo declinfo;
+
+ is_const = 1;
+ has_ass = 0;
+ access = ACCESSPUBLIC;
+
+ if (!CClass_AssignmentOperator(tclass)) {
+ if (!copts.old_argmatch)
+ has_ass = 1;
+
+ if ((tclass->flags & CLASS_FLAGS_20) || decle->xC || CClass_MemberObject(tclass, asop_name_node))
+ has_ass = 1;
+
+ for (base = tclass->bases; base; base = base->next) {
+ if ((obj = CClass_AssignmentOperator(base->base))) {
+ has_ass = 1;
+ access = getaccesstype(access, obj->access, ACCESSPRIVATE);
+ if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST))
+ is_const = 0;
+ }
+ }
+
+ for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
+ Type *type = ivar->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (IS_TYPE_CLASS(type) && (obj = CClass_AssignmentOperator(TYPE_CLASS(type)))) {
+ has_ass = 1;
+ access = getaccesstype(access, obj->access, ACCESSPUBLIC);
+ if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST))
+ is_const = 0;
+ }
+ }
+ }
+
+ if (has_ass) {
+ memclrw(&declinfo, sizeof(DeclInfo));
+ declinfo.qual |= Q_INLINE;
+ declinfo.thetype = (Type *) CDecl_MakeAssignmentOperatorType(tclass, is_const);
+ declinfo.name = asop_name_node;
+ CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0);
+ }
+}
+
+TypeMethod *CDecl_MakeDefaultDtorType(TypeClass *tclass, Boolean is_virtual) {
+ TypeMethod *tmeth = galloc(sizeof(TypeMethod));
+ memclrw(tmeth, sizeof(TypeMethod));
+ tmeth->type = TYPEFUNC;
+ tmeth->functype = (Type *) &void_ptr;
+ tmeth->flags = FUNC_FLAGS_2000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD;
+ tmeth->theclass = tclass;
+ CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1);
+ if (is_virtual)
+ CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort));
+ CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass);
+ return tmeth;
+}
+
+static void CDecl_AddDefaultDestructor(DeclE *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjMemberVar *ivar;
+ Object *obj;
+ short access;
+ Boolean has_dtor;
+ Boolean is_virtual;
+ DeclInfo declinfo;
+
+ if (CClass_Destructor(tclass))
+ return;
+
+ has_dtor = 0;
+ is_virtual = 0;
+ access = ACCESSPUBLIC;
+
+ for (base = tclass->bases; base; base = base->next) {
+ if ((obj = CClass_Destructor(base->base))) {
+ has_dtor = 1;
+ if (obj->datatype == DVFUNC)
+ is_virtual = 1;
+ access = getaccesstype(access, obj->access, ACCESSPRIVATE);
+ }
+ }
+
+ for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
+ Type *type = ivar->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (IS_TYPE_CLASS(type) && (obj = CClass_Destructor(TYPE_CLASS(type)))) {
+ has_dtor = 1;
+ access = getaccesstype(access, obj->access, ACCESSPUBLIC);
+ }
+ }
+
+ if (has_dtor) {
+ memclrw(&declinfo, sizeof(DeclInfo));
+ declinfo.qual |= Q_INLINE;
+ if (is_virtual)
+ declinfo.qual |= Q_VIRTUAL;
+
+ declinfo.thetype = (Type *) CDecl_MakeDefaultDtorType(tclass, 1);
+ declinfo.name = destructor_name_node;
+ CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0);
+ }
+}
+
+static void CDecl_SetupClassLayout(DeclE *decle, TypeClass *tclass, ObjBase **objbuf) {
+ SInt32 index;
+ SInt32 i;
+ Object *obj;
+ CScopeObjectIterator iter;
+ ObjMemberVar *ivar;
+ SInt32 bufsize;
+
+ if (decle->x8 > 32) {
+ bufsize = decle->x8 * sizeof(ObjBase *);
+ objbuf = lalloc(bufsize);
+ } else {
+ bufsize = 32 * sizeof(ObjBase *);
+ }
+ memclrw(objbuf, bufsize);
+ decle->objlist = objbuf;
+
+ CScope_InitObjectIterator(&iter, tclass->nspace);
+ index = 0;
+ while (1) {
+ obj = OBJECT(CScope_NextObjectIteratorObject(&iter));
+ if (!obj) break;
+
+ if (!IS_TYPE_FUNC(obj->type))
+ continue;
+ if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)))
+ continue;
+ if (obj->datatype == DALIAS)
+ continue;
+
+ i = TYPE_METHOD(obj->type)->x1E;
+ if (i > 0) {
+#line 6363
+ CError_ASSERT((i - 1) < decle->x8 && !objbuf[(int) (i - 1)]);
+ objbuf[(int) (i - 1)] = OBJ_BASE(obj);
+ index++;
+ if (obj->datatype != DVFUNC && !TYPE_METHOD(obj->type)->x26 && CClass_OverridesBaseMember(tclass, obj->name, obj))
+ CDecl_MakeFunctionVirtual(tclass, obj);
+
+ if (obj->datatype == DVFUNC) {
+ decle->xC = 1;
+ if (!tclass->vtable) {
+ CABI_AddVTable(tclass);
+ decle->xA = i - 1;
+ } else {
+ if ((i - 1) < decle->xA)
+ decle->xA = i - 1;
+ }
+ } else if (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_8) {
+ CError_Error(351, obj);
+ TYPE_FUNC(obj->type)->flags &= ~FUNC_FLAGS_8;
+ }
+ } else {
+#line 6412
+ CError_ASSERT(i == 0);
+ }
+
+ if (!tclass->sominfo)
+ TYPE_METHOD(obj->type)->x1E = 0;
+ }
+
+ if (!tclass->action) {
+ for (i = 0; i < decle->x8; i++) {
+ Object *obj2 = OBJECT(objbuf[i]);
+ if (obj2 && obj2->datatype == DVFUNC && !(obj2->qual & Q_INLINE) && !(TYPE_FUNC(obj2->type)->flags & FUNC_FLAGS_8)) {
+ tclass->action = CLASS_ACTION_1;
+ TYPE_FUNC(obj2->type)->flags |= FUNC_FLAGS_4;
+ break;
+ }
+ }
+ }
+
+ if (!tclass->sominfo) {
+ for (i = 0, ivar = tclass->ivars; i < decle->x8; i++) {
+ if (!objbuf[i]) {
+#line 6449
+ CError_ASSERT(ivar);
+ objbuf[i] = OBJ_BASE(ivar);
+ ivar = ivar->next;
+ index++;
+ }
+ }
+#line 6455
+ CError_ASSERT(ivar == NULL);
+ }
+
+#line 6458
+ CError_ASSERT(index == decle->x8);
+}
+
+void CDecl_CompleteClass(DeclE *decle, TypeClass *tclass) {
+ ClassList *base;
+ ObjBase *buf[32];
+
+ for (base = tclass->bases; base; base = base->next) {
+ if (base->base->vtable)
+ decle->xC = 1;
+ }
+
+ if (!tclass->sominfo) {
+ CDecl_AddDefaultDestructor(decle, tclass);
+ CDecl_AddDefaultAssignmentOperator(decle, tclass);
+ CDecl_AddDefaultConstructor(decle, tclass);
+ CDecl_AddDefaultCopyConstructor(decle, tclass);
+ }
+
+ CDecl_SetupClassLayout(decle, tclass, buf);
+ if (decle->xC)
+ CClass_CheckOverrides(tclass);
+ CABI_LayoutClass(decle, tclass);
+ if (tclass->sominfo)
+ CSOM_ClassComplete(tclass);
+
+ if ((tclass->flags & CLASS_FLAGS_800) && !TEMPL_CLASS_INST(tclass)->x47)
+ tclass->action = CLASS_ACTION_0;
+
+ if (!tclass->action)
+ CClass_MakeStaticActionClass(tclass);
+ CClass_ClassDefaultFuncAction(tclass);
+}
+
+TypeClass *CDecl_DefineClass(NameSpace *nspace, HashNameNode *name, TypeClass *tclass, short mode, Boolean flag2, Boolean flag3) {
+ NameSpace *mynspace;
+ ObjType *objtype;
+
+ if (!tclass && nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)) {
+#line 6556
+ CError_ASSERT(!flag2);
+ return CTemplClass_DefineNestedClass(TEMPL_CLASS(nspace->theclass), name, mode);
+ }
+
+ mynspace = CScope_NewListNameSpace(name, 1);
+ if (!tclass) {
+ tclass = galloc(sizeof(TypeClass));
+ memclrw(tclass, sizeof(TypeClass));
+ }
+
+ tclass->type = TYPECLASS;
+ tclass->align = 1;
+ tclass->mode = mode;
+ tclass->action = CLASS_ACTION_0;
+ if (name) {
+ tclass->classname = name;
+ if (flag3) {
+ if (flag2) {
+ objtype = galloc(sizeof(ObjType));
+ memclrw(objtype, sizeof(ObjType));
+ objtype->otype = OT_TYPE;
+ objtype->access = ACCESSPUBLIC;
+ objtype->type = (Type *) tclass;
+ CScope_AddObject(nspace, name, OBJ_BASE(objtype));
+ } else {
+ CScope_DefineTypeTag(nspace, name, (Type *) tclass);
+ }
+ }
+ CScope_DefineTypeTag(mynspace, name, (Type *) tclass);
+
+ if (cscope_currentfunc)
+ mynspace->name = CParser_AppendUniqueNameFile(name->name);
+
+ if (copts.direct_to_som && nspace == cscope_root && !strcmp(name->name, "SOMObject"))
+ CSOM_MakeSOMClass(tclass);
+ } else {
+ tclass->classname = CParser_AppendUniqueNameFile("@class");
+ mynspace->name = tclass->classname;
+ }
+
+ tclass->nspace = mynspace;
+ mynspace->theclass = tclass;
+ mynspace->parent = nspace;
+ if (!nspace->is_global)
+ CParser_RegisterNonGlobalClass(tclass);
+
+ return tclass;
+}
+
+void CDecl_ParseClassDeclSpec(UInt8 *declspec) {
+ DeclInfo declinfo;
+
+ if ((tk = lex()) == '(') {
+ memclrw(&declinfo, sizeof(DeclInfo));
+ CParser_ParseDeclSpec(&declinfo, 1);
+ if (declinfo.exportflags & EXPORT_FLAGS_INTERNAL)
+ *declspec |= CLASS_EFLAGS_INTERNAL;
+ if (declinfo.exportflags & EXPORT_FLAGS_IMPORT)
+ *declspec |= CLASS_EFLAGS_IMPORT;
+ if (declinfo.exportflags & EXPORT_FLAGS_EXPORT)
+ *declspec |= CLASS_EFLAGS_EXPORT;
+ if ((tk = lex()) != ')')
+ CError_Error(115);
+ else
+ tk = lex();
+ } else {
+ CError_Error(114);
+ }
+}
+
+static TemplClass *CDecl_SpecializeTemplateClass(TemplClass *tmclass) {
+ tmclass->theclass.nspace->names = 0;
+ tmclass->theclass.nspace->data.list = NULL;
+ tmclass->theclass.ivars = NULL;
+ tmclass->theclass.bases = NULL;
+ tmclass->theclass.vbases = NULL;
+ tmclass->theclass.friends = NULL;
+ tmclass->theclass.vtable = NULL;
+ tmclass->members = NULL;
+ tmclass->instances = NULL;
+ tmclass->pspec_owner = NULL;
+ tmclass->pspecs = NULL;
+ tmclass->actions = NULL;
+ tmclass->lex_order_count = 0;
+ tmclass->align = 0;
+ tmclass->flags = TEMPLCLASS_FLAGS_2;
+ return tmclass;
+}
+
+void CDecl_ParseClass(DeclInfo *declinfo, short mode, Boolean flag1, UInt8 class_declspec) {
+ DeclE decle;
+ TypeClass *tclass;
+ HashNameNode *classname;
+ Type *search;
+ short t;
+ NameSpace *nspace;
+ CScopeParseResult pr;
+ CScopeSave scopesave;
+ BrowseStruct bs;
+ FileOffsetInfo offsetsave;
+ SInt32 offset;
+ Boolean is_templ;
+ Boolean add_to_browse;
+
+ memclrw(&decle, sizeof(DeclE));
+ if (declinfo->x28) {
+ tclass = TYPE_CLASS(declinfo->x28);
+ } else {
+ if (tk == TK_UU_DECLSPEC)
+ CDecl_ParseClassDeclSpec(&class_declspec);
+
+ switch (tk) {
+ case ':':
+ case '{':
+ tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
+ tclass->eflags |= class_declspec;
+ break;
+ case TK_IDENTIFIER:
+ classname = tkidentifier;
+ if (!declinfo->x4C && !declinfo->x4F && ((t = lookahead()) == ':' || t == ';' || t == '{')) {
+ tk = lex();
+ search = CScope_GetLocalTagType(cscope_current, classname);
+ if (search) {
+ tagtype_search:
+ if (!IS_TYPE_CLASS(search)) {
+ if ((IS_TYPE_TEMPLATE(search) || IS_TYPE_STRUCT(search)) && tk != '{' && tk != ':') {
+ declinfo->thetype = search;
+ return;
+ }
+ if (!IS_TYPE_TEMPLATE(search) || !(tclass = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(search)))) {
+ CError_Error(132, classname->name);
+ tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
+ break;
+ }
+ } else {
+ tclass = TYPE_CLASS(search);
+ }
+ if (tclass->mode != mode) {
+ if ((mode == CLASS_FLAGS_2 && tclass->mode == CLASS_MODE_0) || (mode == CLASS_MODE_0 && tclass->mode == CLASS_MODE_2)) {
+ if (copts.warn_structclass)
+ CError_Warning(343);
+ } else {
+ CError_Error(132, classname);
+ }
+ }
+ tclass->eflags |= class_declspec;
+ break;
+ } else {
+ tclass = CDecl_DefineClass(cscope_current, classname, NULL, mode, 0, 1);
+ tclass->eflags |= class_declspec;
+ break;
+ }
+ } else {
+ tkidentifier = classname;
+ }
+ default:
+ if (!CScope_ParseElaborateName(&pr)) {
+ CError_Error(121);
+ declinfo->thetype = (Type *) &stsignedint;
+ return;
+ }
+
+ tk = lex();
+ if ((search = pr.x8)) {
+ goto tagtype_search;
+ }
+
+#line 6786
+ CError_ASSERT(pr.name_4);
+
+ tclass = CDecl_DefineClass(CScope_FindNonClassNonFunctionNS(cscope_current), pr.name_4, NULL, mode, 0, 1);
+ tclass->eflags |= class_declspec;
+ }
+ }
+
+ declinfo->thetype = (Type *) tclass;
+ if (tk == ':' || tk == '{') {
+ if (declinfo->x4C)
+ CError_Error(201);
+
+ if (tclass->flags & CLASS_FLAGS_2) {
+ if ((tclass->flags & CLASS_FLAGS_100) && !TEMPL_CLASS(tclass)->instances && !(TEMPL_CLASS(tclass)->flags & TEMPLCLASS_FLAGS_2)) {
+ tclass = TYPE_CLASS(CDecl_SpecializeTemplateClass(TEMPL_CLASS(tclass)));
+ } else {
+ CError_Error(132, tclass->classname->name);
+ tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
+ }
+ }
+
+ for (nspace = cscope_current; nspace; nspace = nspace->parent) {
+ if (nspace == tclass->nspace) {
+ CError_Error(132, tclass->classname->name);
+ tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1);
+ break;
+ }
+ }
+
+ is_templ = (tclass->flags & CLASS_FLAGS_100) ? 1 : 0;
+ if (tclass->flags & CLASS_FLAGS_800) {
+ TEMPL_CLASS_INST(tclass)->x46 = 1;
+ if (!declinfo->x28)
+ TEMPL_CLASS_INST(tclass)->x47 = 1;
+ }
+
+#line 6853
+ CError_ASSERT(copts.align_mode >= 0 && copts.align_mode <= 14);
+
+ tclass->eflags |= (UInt8) ((copts.align_mode + 1) << 4);
+ if (tk == ':')
+ CDecl_ParseBaseClassList(tclass, mode, is_templ);
+
+ CScope_SetClassDefScope(tclass, &scopesave);
+ if (tk == '{') {
+ tk = lex();
+ if ((add_to_browse = cparamblkptr->browseOptions.recordClasses && declinfo->fileoffsetinfo.file->recordbrowseinfo)) {
+ offsetsave = member_fileoffset;
+ CBrowse_BeginClass(declinfo, &bs);
+ }
+ CDecl_ParseClassMembers(&decle, tclass, mode);
+ offset = CPrep_BrowserFileOffset();
+ if (flag1)
+ tk = lex();
+ if (add_to_browse) {
+ member_fileoffset = offsetsave;
+ if (flag1 && tk == ';')
+ CPrep_BrowserFileOffset();
+ CBrowse_EndClass(offset, &bs);
+ }
+ } else {
+ CError_Error(135);
+ }
+
+ if (is_templ)
+ CTemplClass_CompleteClass(TEMPL_CLASS(tclass), &decle);
+ else
+ CDecl_CompleteClass(&decle, tclass);
+ CScope_RestoreScope(&scopesave);
+ }
+}
diff --git a/compiler_and_linker/unsorted/CExpr.c b/compiler_and_linker/unsorted/CExpr.c
new file mode 100644
index 0000000..e73c4bb
--- /dev/null
+++ b/compiler_and_linker/unsorted/CExpr.c
@@ -0,0 +1,123 @@
+#include "compiler/CExpr.h"
+#include "compiler/CError.h"
+
+Boolean (*name_obj_check)(void *, Object *); // TODO figure out the right type
+Boolean disallowgreaterthan;
+
+void CExpr_RewriteConst() {}
+void optimizecomm() {}
+static void checkadditive() {}
+static void CExpr_CompareConvert() {}
+static void CExpr_ConstResult() {}
+static void makemultnode() {}
+static void makedivnode() {}
+static void canadd2() {}
+void canadd() {}
+static void addconst() {}
+static void integralpointerpromote() {}
+static void padd() {}
+static void psub() {}
+static void makeaddnode() {}
+static void makesubnode() {}
+void checkreference() {}
+static ENode *pointer_generation2(ENode *expr) {}
+ENode *pointer_generation(ENode *expr) {}
+void CExpr_PointerGeneration() {}
+static void CExpr_ConstPointerCheck() {}
+void oldassignmentpromotion() {}
+void argumentpromotion() {}
+void classargument() {}
+ENodeList *CExpr_ScanExpressionList(Boolean flag) {}
+static void skipcommaexpr() {}
+void CExpr_DoExplicitConversion() {}
+static void CExpr_TemplArgDepCast() {}
+static void CExpr_ParseExplicitConversion() {}
+static void CExpr_MemberVarAccess() {}
+static void CExpr_IsTemplateFunc() {}
+static void CExpr_ExplicitTemplateArgCheck() {}
+void CExpr_MakeNameLookupResultExpr() {}
+static void CExpr_NewPTMType() {}
+static void CExpr_ParseNameResultExpr() {}
+static void CExpr_ParseRotate() {}
+static void CExpr_ParseNextArg() {}
+static void CExpr_ParseVecStep() {}
+static void CExpr_BuiltInComputeAlign() {}
+static void CExpr_AtomTypeID() {}
+static void CExpr_BuiltInComputeType() {}
+static void CExpr_BuiltInClassifyType() {}
+static void CExpr_BuiltInComputeVArgType() {}
+static void CExpr_ParseTypeExpression() {}
+static void CExpr_ParseBuiltin() {}
+static void CExpr_ParseBuiltin_isintconst() {}
+static void primary_expression() {}
+static void CExpr_SimpleExplicitConversion() {}
+static void CExpr_NewPTMFCall() {}
+static void call_ptmf() {}
+static void CExpr_DummyDestr() {}
+static void postfix_expression() {}
+static void CExpr_ParseSizeof() {}
+void scansizeof() {}
+static void CExpr_ParseAlignof() {}
+void scanalignof() {}
+static void logicalexpression() {}
+void getnodeaddress() {}
+static void CExpr_MakeStaticMemberList() {}
+static void CExpr_MakePTDM() {}
+void getpointertomemberfunc() {}
+static void getpointertomember() {}
+void CExpr_New_ELOGNOT_Node() {}
+void CExpr_New_EMONMIN_Node() {}
+void CExpr_New_EBINNOT_Node() {}
+void unary_expression() {}
+void do_castnullcheck() {}
+void CExpr_SafeClassPointerCast() {}
+void PointerToMemberCast() {}
+void CExpr_MemberPointerConversion() {}
+static void CExpr_MemberPointerCast() {}
+void do_typecast() {}
+static void isvectorconst() {}
+void cast_expression() {}
+static void pm_expression() {}
+void CExpr_New_EMUL_Node() {}
+void CExpr_New_EDIV_Node() {}
+void CExpr_New_EMODULO_Node() {}
+void CExpr_New_EADD_Node() {}
+void CExpr_New_ESUB_Node() {}
+void CExpr_New_ESHL_Node() {}
+void CExpr_New_ESHR_Node() {}
+static void pointercompare() {}
+static void unsigncheck() {}
+void CExpr_New_ELESS_Node() {}
+void CExpr_New_ELESSEQU_Node() {}
+void CExpr_New_EGREATER_Node() {}
+void CExpr_New_EGREATEREQU_Node() {}
+void memberpointercompare() {}
+void CExpr_New_EEQU_Node() {}
+void CExpr_New_ENOTEQU_Node() {}
+void CExpr_New_EAND_Node() {}
+void CExpr_New_EXOR_Node() {}
+void CExpr_New_EOR_Node() {}
+void CExpr_New_ELAND_Node() {}
+void CExpr_New_ELOR_Node() {}
+void CExpr_NewDyadicNode() {}
+static void CExpr_GetDyadicInfo() {}
+static void CExpr_ParseDyadicExpression() {}
+static void CExpr_IsBlockMoveType() {}
+void CExpr_New_ECOND_Node() {}
+static void conditional_expression() {}
+static void CExpr_MakeOpAssNode() {}
+static void makeassignmentnode() {}
+static void makepassignmentnode() {}
+static void makemulassignmentnode() {}
+static void CExpr_TransformOpAssign() {}
+ENode *assignment_expression(void) {}
+ENode *conv_assignment_expression(void) {}
+static void CExpr_HasSideEffect() {}
+void CExpr_CheckUnusedExpression() {}
+void s_expression() {}
+ENode *expression(void) {}
+void CExpr_IntegralConstExprType() {}
+ENode *CExpr_IntegralConstOrDepExpr(void) {}
+void CExpr_IntegralConstExpr() {}
+void CExpr_CheckUnwantedAssignment() {}
+void CExpr_ParseAsmExpr() {}
diff --git a/compiler_and_linker/unsorted/CExpr2.c b/compiler_and_linker/unsorted/CExpr2.c
new file mode 100644
index 0000000..6679bce
--- /dev/null
+++ b/compiler_and_linker/unsorted/CExpr2.c
@@ -0,0 +1,1934 @@
+#include "compiler/CExpr.h"
+#include "compiler/CABI.h"
+#include "compiler/CClass.h"
+#include "compiler/CDecl.h"
+#include "compiler/CInt64.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInline.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CScope.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+
+#ifdef __MWERKS__
+#undef va_start
+#undef va_arg
+#define va_start(ap, parm) ap = __va_start(parm)
+#define __va_start(parm) (va_list) (&parm + 1)
+//#define va_arg(ap, type) ((((type *) (ap = (va_list) (( ((long) ap + sizeof(type) - 1) & ~(sizeof(type)) ) + sizeof(type) ) ))[-1]))
+#define va_arg(ap, type) (*(((type *) (ap = (char *)((((unsigned long)ap + __builtin_align(type) - 1) & ~(__builtin_align(type) - 1) ) + sizeof(type)))) - 1))
+#endif
+
+// TODO MOVE ME
+extern ENode *CSOM_EnvCheck(ENode *, ENodeList *);
+extern Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr);
+extern ENode *CTemplTool_DeduceDefaultArg(Object *func, ENode *expr);
+extern Boolean CObjC_IsCompatibleType(Type *a, Type *b);
+
+ENode *assign_node;
+Boolean temp_reference_init;
+static SInt32 assign_value; // type?
+static ENode *firstarrayexpr;
+static Match5 user_std_match;
+static Boolean cexpr_hascall;
+static Boolean cexpr_esearch_bool[MAXEXPR];
+static Boolean cexpr_rsearch_bool[MAXEXPR];
+static CExprSearchCB cexpr_esearch_callback;
+static CExprReplaceCB cexpr_rsearch_callback;
+static Type *cexpr_left_conversion_type;
+static Type *cexpr_right_conversion_type;
+
+// data objects, need to figure out the types
+static void *diadic_arg1;
+static void *diadic_arg2;
+static void *mon_arg;
+
+static void CExpr_RecSearchExprTree(ENode *expr) {
+ ENodeList *list;
+
+restart:
+ if (cexpr_esearch_bool[expr->type])
+ cexpr_esearch_callback(expr);
+
+ switch (expr->type) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EINDIRECT:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ expr = expr->data.monadic;
+ goto restart;
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ CExpr_RecSearchExprTree(expr->data.diadic.left);
+ expr = expr->data.diadic.right;
+ goto restart;
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EPRECOMP:
+ case ETEMP:
+ case EARGOBJ:
+ case ELOCOBJ:
+ case ELABEL:
+ case EOBJLIST:
+ case EMEMBER:
+ case EINSTRUCTION:
+ case EVECTOR128CONST:
+ return;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ for (list = expr->data.funccall.args; list; list = list->next)
+ CExpr_RecSearchExprTree(list->node);
+ expr = expr->data.funccall.funcref;
+ goto restart;
+ case ENULLCHECK:
+ CExpr_RecSearchExprTree(expr->data.nullcheck.nullcheckexpr);
+ expr = expr->data.nullcheck.condexpr;
+ goto restart;
+ case EMFPOINTER:
+ CExpr_RecSearchExprTree(expr->data.mfpointer.accessnode);
+ expr = expr->data.mfpointer.mfpointer;
+ goto restart;
+ case ECOND:
+ CExpr_RecSearchExprTree(expr->data.cond.cond);
+ CExpr_RecSearchExprTree(expr->data.cond.expr1);
+ expr = expr->data.cond.expr2;
+ goto restart;
+ case ENEWEXCEPTION:
+ case ENEWEXCEPTIONARRAY:
+ CExpr_RecSearchExprTree(expr->data.newexception.initexpr);
+ expr = expr->data.newexception.tryexpr;
+ goto restart;
+ case EMYSTERY67:
+ if (expr->data.itc.initexpr)
+ CExpr_RecSearchExprTree(expr->data.itc.initexpr);
+ if (expr->data.itc.tryexpr)
+ CExpr_RecSearchExprTree(expr->data.itc.tryexpr);
+ if (expr->data.itc.catchexpr)
+ CExpr_RecSearchExprTree(expr->data.itc.catchexpr);
+ if (expr->data.itc.result)
+ CExpr_RecSearchExprTree(expr->data.itc.result);
+ return;
+ default:
+#line 128
+ CError_FATAL();
+ }
+}
+
+void CExpr_SearchExprTree(ENode *expr, CExprSearchCB callback, int count, ...) {
+ va_list ap;
+ short i;
+
+ cexpr_esearch_callback = callback;
+
+ va_start(ap, count);
+ for (i = 0; i < MAXEXPR; i++)
+ cexpr_esearch_bool[i] = 0;
+ i = 0;
+ while ((short) i < count) {
+ cexpr_esearch_bool[va_arg(ap, int)] = 1;
+ ++i;
+ }
+ va_end(ap);
+
+ CExpr_RecSearchExprTree(expr);
+}
+
+static ENode *CExpr_RecSearchExprTreeReplace(ENode *expr) {
+ ENodeList *list;
+ ENode *replaced;
+
+ if (cexpr_rsearch_bool[expr->type]) {
+ replaced = cexpr_rsearch_callback(expr);
+ if (!replaced)
+ return expr;
+ expr = replaced;
+ }
+
+ switch (expr->type) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EINDIRECT:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ expr->data.monadic = CExpr_RecSearchExprTreeReplace(expr->data.monadic);
+ return expr;
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ expr->data.diadic.left = CExpr_RecSearchExprTreeReplace(expr->data.diadic.left);
+ expr->data.diadic.right = CExpr_RecSearchExprTreeReplace(expr->data.diadic.right);
+ return expr;
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EPRECOMP:
+ case ETEMP:
+ case EARGOBJ:
+ case ELOCOBJ:
+ case ELABEL:
+ case EMEMBER:
+ case EINSTRUCTION:
+ case EVECTOR128CONST:
+ return expr;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ for (list = expr->data.funccall.args; list; list = list->next)
+ list->node = CExpr_RecSearchExprTreeReplace(list->node);
+ expr->data.funccall.funcref = CExpr_RecSearchExprTreeReplace(expr->data.funccall.funcref);
+ return expr;
+ case ENULLCHECK:
+ expr->data.nullcheck.nullcheckexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.nullcheckexpr);
+ expr->data.nullcheck.condexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.condexpr);
+ return expr;
+ case EMFPOINTER:
+ expr->data.mfpointer.accessnode = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.accessnode);
+ expr->data.mfpointer.mfpointer = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.mfpointer);
+ return expr;
+ case ECOND:
+ expr->data.cond.cond = CExpr_RecSearchExprTreeReplace(expr->data.cond.cond);
+ expr->data.cond.expr1 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr1);
+ expr->data.cond.expr2 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr2);
+ return expr;
+ default:
+#line 220
+ CError_FATAL();
+ return NULL;
+ }
+}
+
+ENode *CExpr_SearchExprTreeReplace(ENode *expr, CExprReplaceCB callback, int count, ...) {
+ va_list ap;
+ short i;
+
+ cexpr_rsearch_callback = callback;
+
+ va_start(ap, count);
+ for (i = 0; i < MAXEXPR; i++)
+ cexpr_rsearch_bool[i] = 0;
+ i = 0;
+ while ((short) i < count) {
+ cexpr_rsearch_bool[va_arg(ap, int)] = 1;
+ ++i;
+ }
+ va_end(ap);
+
+ return CExpr_RecSearchExprTreeReplace(expr);
+}
+
+static void CExpr_HasFuncCallCallBack(ENode *expr) {
+ cexpr_hascall = 1;
+}
+
+Boolean CExpr_HasFuncCall(ENode *expr) {
+ cexpr_hascall = 0;
+ CExpr_SearchExprTree(expr, CExpr_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP);
+ return cexpr_hascall;
+}
+
+void CExpr_AliasTransform(ENode *expr) {
+ ENode *n;
+
+ Object *obj = expr->data.objref;
+ if (obj->u.alias.offset) {
+ n = makediadicnode(
+ create_objectrefnode(obj->u.alias.object),
+ intconstnode(TYPE(&stunsignedlong), obj->u.alias.offset),
+ EADD);
+ *expr = *n;
+ } else {
+ expr->data.objref = obj->u.alias.object;
+ }
+}
+
+ENode *CExpr_UnaryFloatExpression(ENode *expr) {
+ return expr;
+}
+
+ENode *CExpr_BinaryFloatExpression(ENode *expr) {
+ return expr;
+}
+
+ENode *CExpr_NewENode(ENodeType ty) {
+ ENode *expr = lalloc(sizeof(ENode));
+ memclrw(expr, sizeof(ENode));
+ expr->type = ty;
+ return expr;
+}
+
+ENode *CExpr_NewTemplDepENode(TemplDepSubType t) {
+ ENode *expr = CExpr_NewENode(ETEMPLDEP);
+ expr->rtype = &sttemplexpr;
+ expr->data.templdep.subtype = t;
+ return expr;
+}
+
+ENode *nullnode(void) {
+ ENode *expr = CExpr_NewENode(EINTCONST);
+ expr->rtype = (Type *) &stsignedlong;
+ return expr;
+}
+
+ENode *intconstnode(Type *type, SInt32 value) {
+ ENode *expr = CExpr_NewENode(EINTCONST);
+ expr->rtype = type;
+ CInt64_SetLong(&expr->data.intval, value);
+ return expr;
+}
+
+ENode *stringconstnode(char *str) {
+ ENode *expr;
+ SInt32 size;
+
+ size = strlen(str) + 1;
+ expr = CExpr_NewENode(ESTRINGCONST);
+ expr->rtype = CDecl_NewArrayType((Type *) &stchar, size);
+ expr->data.string.size = size;
+ expr->data.string.data = str;
+ expr->data.string.ispascal = 0;
+ if (copts.const_strings)
+ expr->flags = Q_CONST;
+
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype);
+ return expr;
+}
+
+ENode *forceintegral(ENode *expr) {
+ if (!IS_TYPE_ENUM(expr->rtype)) {
+ CError_Error(144);
+ return nullnode();
+ } else {
+ expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
+ return expr;
+ }
+}
+
+ENode *makemonadicnode(ENode *inner, ENodeType ty) {
+ ENode *expr = lalloc(sizeof(ENode));
+ expr->type = ty;
+ if ((expr->cost = inner->cost) == 0)
+ expr->cost = 1;
+ expr->flags = inner->flags & ENODE_FLAG_QUALS;
+ expr->rtype = inner->rtype;
+ expr->data.monadic = inner;
+ return expr;
+}
+
+ENode *makediadicnode(ENode *left, ENode *right, ENodeType ty) {
+ ENode *expr = lalloc(sizeof(ENode));
+ expr->type = ty;
+ expr->rtype = left->rtype;
+ expr->data.diadic.left = left;
+ expr->data.diadic.right = right;
+
+ if (left->cost != right->cost) {
+ expr->cost = right->cost;
+ if (left->cost > expr->cost)
+ expr->cost = left->cost;
+ } else {
+ expr->cost = right->cost + 1;
+ if (expr->cost > 200)
+ expr->cost = 200;
+ }
+
+ expr->flags = (left->flags | right->flags) & ENODE_FLAG_QUALS;
+ return expr;
+}
+
+ENode *makecommaexpression(ENode *left, ENode *right) {
+ ENode *expr;
+
+ if (ENODE_IS(right, EINDIRECT) && !ENODE_IS(right->data.monadic, EBITFIELD)) {
+ Boolean savecpp = copts.cplusplus;
+ copts.cplusplus = 1;
+ expr = makediadicnode(left, getnodeaddress(right, 0), ECOMMA);
+ copts.cplusplus = savecpp;
+ expr->rtype = expr->data.diadic.right->rtype;
+ expr = makemonadicnode(expr, EINDIRECT);
+ } else {
+ expr = makediadicnode(left, right, ECOMMA);
+ }
+
+ expr->rtype = right->rtype;
+ expr->flags = right->flags;
+ return expr;
+}
+
+short iszero(ENode *expr) {
+ switch (expr->type) {
+ case EINTCONST:
+ return CInt64_IsZero(&expr->data.intval);
+ case EFLOATCONST:
+ return CMach_FloatIsZero(expr->data.floatval);
+ default:
+ return 0;
+ }
+}
+
+short isnotzero(ENode *expr) {
+ Object *obj;
+
+ switch (expr->type) {
+ case EINTCONST:
+ return !CInt64_IsZero(&expr->data.intval);
+ case EFLOATCONST:
+ return !CMach_FloatIsZero(expr->data.floatval);
+ case ESTRINGCONST:
+ case ETEMP:
+ return 1;
+ case EOBJREF:
+ obj = expr->data.objref;
+ break;
+ case EADD:
+ case ESUB:
+ if (ENODE_IS(expr->data.diadic.left, EOBJREF) && ENODE_IS(expr->data.diadic.right, EINTCONST)) {
+ obj = expr->data.diadic.left->data.objref;
+ break;
+ }
+ if (ENODE_IS(expr->data.diadic.left, EINTCONST) && ENODE_IS(expr->data.diadic.right, EOBJREF)) {
+ obj = expr->data.diadic.right->data.objref;
+ break;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+
+ switch (obj->datatype) {
+ case DLOCAL:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+Boolean CExpr_IsOne(ENode *expr) {
+ if (ENODE_IS(expr, EINTCONST))
+ return CInt64_Equal(expr->data.intval, cint64_one);
+ else if (ENODE_IS(expr, EFLOATCONST))
+ return CMach_FloatIsOne(expr->data.floatval);
+ else
+ return 0;
+}
+
+Boolean CExpr_AllBitsSet(ENode *expr) {
+ SInt32 v;
+
+ if (ENODE_IS(expr, EINTCONST)) {
+ switch (expr->rtype->size) {
+ case 1:
+ v = CInt64_GetULong(&expr->data.intval) & 0xFF;
+ return v == 0xFF;
+ case 2:
+ v = CInt64_GetULong(&expr->data.intval) & 0xFFFF;
+ return v == 0xFFFF;
+ case 3:
+ v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFF;
+ return v == 0xFFFFFF;
+ case 4:
+ v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFFFF;
+ return v == 0xFFFFFFFF;
+ default:
+ return CInt64_Equal(expr->data.intval, cint64_negone);
+ }
+ }
+
+ return 0;
+}
+
+ENode *CExpr_NewETEMPNode(Type *type, Boolean assign_id) {
+ ENode *expr = lalloc(sizeof(ENode));
+ expr->type = ETEMP;
+ expr->cost = 0;
+ expr->flags = 0;
+ expr->rtype = CDecl_NewPointerType(type);
+ expr->data.temp.type = type;
+ expr->data.temp.uniqueid = assign_id ? CParser_GetUniqueID() : 0;
+ expr->data.temp.needs_dtor = 0;
+ return expr;
+}
+
+static ENode *CExpr_DerefETEMPCopy(ENode *expr) {
+ ENode *copy;
+
+#line 636
+ CError_ASSERT(expr->rtype->type == TYPEPOINTER);
+
+ copy = lalloc(sizeof(ENode));
+ *copy = *expr;
+ copy = makemonadicnode(copy, EINDIRECT);
+ copy->rtype = TYPE_POINTER(copy->rtype)->target;
+}
+
+ENode *CExpr_GetETEMPCopy(ENode *expr) {
+ ENode *newnode;
+ ENode *assnode;
+ ENode *finalnode;
+
+ newnode = CExpr_NewETEMPNode(expr->rtype, 1);
+ newnode->flags = expr->flags;
+
+ assnode = makediadicnode(CExpr_DerefETEMPCopy(newnode), expr, EASS);
+ assnode->data.diadic.right = lalloc(sizeof(ENode));
+ *assnode->data.diadic.right = *expr;
+ *expr = *assnode;
+
+ finalnode = makemonadicnode(newnode, EINDIRECT);
+ finalnode->rtype = expr->rtype;
+ return finalnode;
+}
+
+ENode *integralpromote(ENode *expr) {
+ if (!IS_TYPE_INT(expr->rtype))
+ expr = forceintegral(expr);
+
+ if (TYPE_INTEGRAL(expr->rtype)->integral >= IT_INT)
+ return expr;
+
+ if (!ENODE_IS(expr, EINTCONST))
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = (Type *) &stsignedint;
+
+ return expr;
+}
+
+CInt64 CExpr_IntConstConvert(Type *a, Type *b, CInt64 val) {
+ if (a == (Type *) &stbool)
+ return CMach_CalcIntDiadic(b, val, TK_LOGICAL_NE, cint64_zero);
+ else
+ return CMach_CalcIntDiadic(a, val, '+', cint64_zero);
+}
+
+ENode *promote(ENode *expr, Type *type) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ if (IS_TYPE_FLOAT(type)) {
+ expr->type = EFLOATCONST;
+ expr->data.floatval = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval);
+ } else {
+ expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval);
+ }
+ expr->rtype = type;
+ return expr;
+ }
+ if (ENODE_IS(expr, EFLOATCONST)) {
+ if (IS_TYPE_FLOAT(type)) {
+ expr->data.floatval = CMach_CalcFloatConvert(type, expr->data.floatval);
+ expr->rtype = type;
+ return expr;
+ } else if (IS_TYPE_INT(type)) {
+ expr->data.intval = CMach_CalcIntConvertFromFloat(type, expr->data.floatval);
+ expr->type = EINTCONST;
+ expr->rtype = type;
+ return expr;
+ }
+ }
+
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = type;
+ return expr;
+}
+
+void CExpr_ArithmeticConversion(ENode **left, ENode **right) {
+ switch ((*left)->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ break;
+ case TYPEENUM:
+ (*left)->rtype = TYPE_ENUM((*left)->rtype)->enumtype;
+ break;
+ default:
+ CError_Error(144);
+ (*left) = nullnode();
+ }
+
+ switch ((*right)->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ break;
+ case TYPEENUM:
+ (*right)->rtype = TYPE_ENUM((*right)->rtype)->enumtype;
+ break;
+ default:
+ CError_Error(144);
+ (*right) = nullnode();
+ }
+
+ if (IS_TYPE_FLOAT((*left)->rtype) || IS_TYPE_FLOAT((*right)->rtype)) {
+ if ((*left)->rtype != (*right)->rtype) {
+ if (TYPE_INTEGRAL((*left)->rtype)->integral > TYPE_INTEGRAL((*right)->rtype)->integral)
+ *right = promote(*right, (*left)->rtype);
+ else
+ *left = promote(*left, (*right)->rtype);
+ }
+ return;
+ }
+
+ *left = integralpromote(*left);
+ *right = integralpromote(*right);
+ if ((*left)->rtype != (*right)->rtype) {
+ if (TYPE_INTEGRAL((*left)->rtype)->integral < TYPE_INTEGRAL((*right)->rtype)->integral) {
+ ENode **tmp = left;
+ left = right;
+ right = tmp;
+ }
+
+ if ((*left)->rtype->size == (*right)->rtype->size && !is_unsigned((*left)->rtype) && is_unsigned((*right)->rtype)) {
+ if ((*left)->rtype == (Type *) &stsignedlong) {
+ *left = promote(*left, (Type *) &stunsignedlong);
+ } else {
+#line 838
+ CError_ASSERT((*left)->rtype == (Type *) &stsignedlonglong);
+ *left = promote(*left, (Type *) &stunsignedlonglong);
+ }
+ }
+
+ *right = promote(*right, (*left)->rtype);
+ }
+}
+
+static ENode *CExpr_GetEA(ENode *expr) {
+ ENode *copy;
+
+ for (;;) {
+ switch (expr->type) {
+ case EINDIRECT:
+ expr = expr->data.monadic;
+ for (;;) {
+ switch (expr->type) {
+ case EOBJREF:
+ copy = lalloc(sizeof(ENode));
+ *copy = *expr;
+ return copy;
+ case ECOMMA:
+ expr = expr->data.diadic.right;
+ continue;
+ default:
+ return CExpr_GetETEMPCopy(expr);
+ }
+ }
+ break;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ expr = expr->data.monadic;
+ continue;
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ expr = expr->data.monadic;
+ continue;
+ case ECOMMA:
+ expr = expr->data.diadic.right;
+ continue;
+ default:
+ return NULL;
+ }
+ }
+}
+
+ENode *CExpr_TempModifyExpr(ENode *expr) {
+ // register issues
+ Type *type;
+ ENode *tempnode;
+ ENode *eanode;
+ ENode *assnode2;
+ ENode *left;
+ ENode *right;
+ ENode *work;
+
+ type = expr->rtype;
+ tempnode = CExpr_NewETEMPNode(type, 1);
+ eanode = CExpr_GetEA(expr);
+ if (!eanode) {
+ CError_Error(142);
+ return expr;
+ }
+
+ left = makemonadicnode(tempnode, EINDIRECT);
+ left->rtype = type;
+ work = makediadicnode(left, expr, EASS);
+
+ left = makemonadicnode(eanode, EINDIRECT);
+ left->rtype = type;
+ right = nullnode();
+ right->rtype = (Type *) &stbool;
+ CInt64_SetLong(&right->data.intval, 1);
+ assnode2 = makediadicnode(left, right, EASS);
+
+ work = makediadicnode(work, assnode2, ECOMMA);
+ right = makemonadicnode(tempnode, EINDIRECT);
+ right->rtype = type;
+ work = makediadicnode(work, right, ECOMMA);
+
+ return work;
+}
+
+Boolean CExpr_IsLValue(ENode *expr) {
+ while (!ENODE_IS(expr, EINDIRECT)) {
+ switch (expr->type) {
+ case EPREINC:
+ case EPREDEC:
+ return copts.cplusplus;
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ if (!copts.cplusplus)
+ return 0;
+ expr = expr->data.diadic.left;
+ continue;
+ case ECOMMA:
+ if (!copts.cplusplus)
+ return 0;
+ expr = expr->data.diadic.right;
+ continue;
+ case ECOND:
+ if (
+ copts.cplusplus &&
+ is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) &&
+ (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS))
+ ) {
+ return CExpr_IsLValue(expr->data.cond.expr1) && CExpr_IsLValue(expr->data.cond.expr2);
+ }
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ expr = expr->data.monadic;
+ switch (expr->type) {
+ case ETEMP:
+ return 0;
+ case EFUNCCALL:
+ if (expr->data.funccall.functype->functype->type != TYPEPOINTER || (expr->data.funccall.functype->flags & FUNC_FLAGS_1000))
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+ENode *CExpr_LValue(ENode *expr, Boolean flag1, Boolean flag2) {
+ ENode *eanode;
+ ENode *tmpnode;
+
+loop:
+ switch (expr->type) {
+ case ETYPCON:
+ if (copts.pointercast_lvalue || !copts.ANSI_strict) {
+ if (expr->rtype->type == TYPEPOINTER && expr->data.monadic->rtype->type == TYPEPOINTER) {
+ switch (expr->data.monadic->type) {
+ case EINDIRECT:
+ case ETYPCON:
+ expr->data.monadic->rtype = expr->rtype;
+ expr->data.monadic->flags = expr->flags;
+ expr = expr->data.monadic;
+ goto loop;
+ }
+ }
+ }
+ break;
+ case EINDIRECT:
+ if (flag2) {
+ if (!CExpr_IsLValue(expr))
+ CError_Warning(142);
+
+ if (
+ ENODE_IS(expr->data.monadic, EOBJREF) &&
+ expr->data.monadic->data.objref->name == this_name_node &&
+ cscope_currentfunc &&
+ cscope_currentclass &&
+ expr->data.monadic->data.objref == CClass_ThisSelfObject())
+ CError_Error(189);
+ }
+ if (flag1) {
+ if (CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS))
+ CError_Error(179);
+ }
+ return expr;
+ case EPREINC:
+ case EPREDEC:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ if (copts.cplusplus) {
+ if ((eanode = CExpr_GetEA(expr))) {
+ tmpnode = makediadicnode(expr, eanode, ECOMMA);
+ tmpnode->rtype = tmpnode->data.diadic.right->rtype;
+ tmpnode = makemonadicnode(tmpnode, EINDIRECT);
+ tmpnode->rtype = expr->rtype;
+ return tmpnode;
+ }
+ CError_Error(190);
+ return expr;
+ }
+ break;
+ case ECOND:
+ if (
+ copts.cplusplus &&
+ is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) &&
+ (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS))
+ ) {
+ expr->data.cond.expr1 = CExpr_LValue(expr->data.cond.expr1, flag1, flag2);
+ expr->data.cond.expr2 = CExpr_LValue(expr->data.cond.expr2, flag1, flag2);
+ if (ENODE_IS(expr->data.cond.expr1, EINDIRECT) && ENODE_IS(expr->data.cond.expr2, EINDIRECT)) {
+ if (!ENODE_IS(expr->data.cond.expr1->data.monadic, EBITFIELD) && !ENODE_IS(expr->data.cond.expr2->data.monadic, EBITFIELD)) {
+ expr->data.cond.expr1 = getnodeaddress(expr->data.cond.expr1, 0);
+ expr->data.cond.expr2 = getnodeaddress(expr->data.cond.expr2, 0);
+ expr->rtype = expr->data.cond.expr1->rtype;
+ tmpnode = makemonadicnode(expr, EINDIRECT);
+ tmpnode->rtype = TYPE_POINTER(tmpnode->rtype)->target;
+ return tmpnode;
+ }
+ }
+ }
+ break;
+ }
+
+ if (flag2)
+ CError_Error(142);
+ return expr;
+}
+
+ENode *CExpr_MakeObjRefNode(Object *obj, Boolean flag) {
+ ENode *expr;
+
+ if (obj->sclass == OBJECT_SCLASS_104) {
+ CError_Error(141);
+ return intconstnode((Type *) &void_ptr, 0);
+ }
+
+ expr = lalloc(sizeof(ENode));
+ memclrw(expr, sizeof(ENode));
+ expr->type = EOBJREF;
+ expr->data.objref = obj;
+ expr->rtype = CDecl_NewPointerType(obj->type);
+
+ if (!IS_TYPE_FUNC(obj->type))
+ expr->flags = obj->qual & ENODE_FLAG_QUALS;
+ if (flag)
+ obj->flags |= OBJECT_FLAGS_UNUSED;
+
+ return expr;
+}
+
+ENode *create_objectrefnode(Object *obj) {
+ if (name_obj_check && !name_obj_check(NULL, obj))
+ return intconstnode((Type *) &void_ptr, 0);
+ return CExpr_MakeObjRefNode(obj, 1);
+}
+
+ENode *create_objectnode2(Object *obj) {
+ ENode *expr;
+
+ if (name_obj_check && !name_obj_check(NULL, obj))
+ return nullnode();
+
+ expr = makemonadicnode(CExpr_MakeObjRefNode(obj, 1), EINDIRECT);
+ expr->rtype = TYPE_POINTER(expr->rtype)->target;
+ return expr;
+}
+
+ENode *create_objectnode(Object *obj) {
+ return checkreference(create_objectnode2(obj));
+}
+
+static ENode *CExpr_ExpandArg(ENode *expr, Type *type) {
+ if (ENODE_IS(expr, ETYPCON) && IS_TYPE_FLOAT(type)) {
+ expr->rtype = type;
+ return expr;
+ } else {
+ return promote(expr, type);
+ }
+}
+
+ENode *CExpr_IsTempConstruction(ENode *expr, Type *type, ENode **resultexpr) {
+ ENodeList *args;
+ ENode *funccall;
+ ENode *funcref;
+
+ if (!ENODE_IS(expr, EINDIRECT) || expr->rtype != type || !ENODE_IS((funccall = expr->data.monadic), EFUNCCALL) || !(args = funccall->data.funccall.args))
+ return NULL;
+
+ if (!ENODE_IS((funcref = funccall->data.funccall.funcref), EOBJREF) || !CClass_IsConstructor(funcref->data.objref)) {
+ if (expr->data.monadic->data.funccall.functype->functype != type)
+ return NULL;
+ if (CABI_GetStructResultArgumentIndex() == 1) {
+ args = args->next;
+#line 1277
+ CError_ASSERT(args);
+ }
+ }
+
+ if (resultexpr)
+ *resultexpr = args->node;
+ return expr->data.monadic;
+}
+
+ENode *CExpr_AdjustFunctionCall(ENode *expr) {
+ ENodeList *list;
+
+ switch (expr->data.funccall.functype->functype->type) {
+ case TYPECLASS:
+ CDecl_CompleteType(expr->data.funccall.functype->functype);
+ case TYPESTRUCT:
+ if (!expr->data.funccall.functype->functype->size)
+ CError_Error(136, expr->data.funccall.functype->functype, 0);
+ }
+
+ if (CMach_GetFunctionResultClass(expr->data.funccall.functype)) {
+ list = lalloc(sizeof(ENodeList));
+ if (IS_TYPE_CLASS(expr->data.funccall.functype->functype)) {
+ CDecl_CompleteType(expr->data.funccall.functype->functype);
+ if (CClass_Destructor(TYPE_CLASS(expr->data.funccall.functype->functype)))
+ list->node = create_temp_node2(expr->rtype);
+ else
+ list->node = create_temp_node(expr->rtype);
+ } else {
+ list->node = create_temp_node(expr->rtype);
+ }
+ list->next = expr->data.funccall.args;
+ expr->data.funccall.args = list;
+
+ if (expr->data.funccall.funcref->flags & ENODE_FLAG_10)
+ expr = CSOM_EnvCheck(expr, list);
+
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype);
+ return expr;
+ }
+
+ if (expr->data.funccall.funcref->flags & ENODE_FLAG_10)
+ expr = CSOM_EnvCheck(expr, NULL);
+ return expr;
+}
+
+ENode *funccallexpr(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4) {
+ ENode *expr;
+ TypeFunc *tfunc;
+ ENodeList *list;
+
+ tfunc = TYPE_FUNC(func->type);
+#line 1411
+ CError_ASSERT(IS_TYPE_FUNC(tfunc));
+
+ expr = lalloc(sizeof(ENode));
+ expr->type = EFUNCCALL;
+ expr->cost = 4;
+ expr->rtype = tfunc->functype;
+ expr->flags = tfunc->qual & ENODE_FLAG_QUALS;
+ expr->data.funccall.funcref = create_objectrefnode(func);
+ expr->data.funccall.functype = tfunc;
+
+ if (arg1) {
+ list = lalloc(sizeof(ENodeList));
+ expr->data.funccall.args = list;
+ list->node = arg1;
+ if (arg2) {
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg2;
+ if (arg3) {
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg3;
+ if (arg4) {
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg4;
+ }
+ }
+ }
+ list->next = NULL;
+ } else {
+ expr->data.funccall.args = NULL;
+ }
+
+ return CExpr_AdjustFunctionCall(expr);
+}
+
+ENode *CExpr_FuncCallSix(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4, ENode *arg5, ENode *arg6) {
+ ENode *expr;
+ TypeFunc *tfunc;
+ ENodeList *list;
+
+ tfunc = TYPE_FUNC(func->type);
+#line 1460
+ CError_ASSERT(IS_TYPE_FUNC(tfunc));
+
+ expr = lalloc(sizeof(ENode));
+ expr->type = EFUNCCALL;
+ expr->cost = 4;
+ expr->rtype = tfunc->functype;
+ expr->flags = tfunc->qual & ENODE_FLAG_QUALS;
+ expr->data.funccall.funcref = create_objectrefnode(func);
+ expr->data.funccall.functype = tfunc;
+
+ list = lalloc(sizeof(ENodeList));
+ expr->data.funccall.args = list;
+ list->node = arg1;
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg2;
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg3;
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg4;
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg5;
+ if (arg6) {
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = arg6;
+ }
+ list->next = NULL;
+
+ return CExpr_AdjustFunctionCall(expr);
+}
+
+static void CExpr_CalcStdAssign(short checkresult, Match5 *match, Type *t1, UInt32 q1, Type *t2, UInt32 q2, Boolean flag) {
+ memclrw(match, sizeof(Match5));
+ switch (checkresult) {
+ case CheckResult1:
+ match->x0++;
+ break;
+ case CheckResult2:
+ match->x2++;
+ break;
+ case CheckResult3:
+ match->x4++;
+ match->x6 += assign_value;
+ break;
+ default:
+#line 1504
+ CError_FATAL();
+ }
+
+ if (flag || (IS_TYPE_POINTER_ONLY(t2) && (IS_TYPE_POINTER_ONLY(t1) || IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) != 0)) {
+ if ((q2 & Q_CONST) == (q1 & Q_CONST))
+ match->x8++;
+ if ((q2 & Q_VOLATILE) == (q1 & Q_VOLATILE))
+ match->x8++;
+ }
+}
+
+void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match) {
+ Boolean r8;
+
+ if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) {
+ t2 = TYPE_POINTER(t2)->target;
+ r8 = 1;
+ } else {
+ r8 = 0;
+ }
+
+ while (IS_TYPE_POINTER_ONLY(t2) && IS_TYPE_POINTER_ONLY(t1)) {
+ if (r8) {
+ if ((TYPE_POINTER(t1)->qual & Q_CONST) != (TYPE_POINTER(t2)->qual & Q_CONST))
+ match->xC--;
+ if ((TYPE_POINTER(t1)->qual & Q_VOLATILE) != (TYPE_POINTER(t2)->qual & Q_VOLATILE))
+ match->xC--;
+ }
+ t2 = TYPE_POINTER(t2)->target;
+ t1 = TYPE_POINTER(t1)->target;
+ r8 = 1;
+ }
+
+ if ((q1 & Q_CONST) != (q2 & Q_CONST))
+ match->xC--;
+ if ((q1 & Q_VOLATILE) != (q2 & Q_VOLATILE))
+ match->xC--;
+}
+
+Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match) {
+ switch (assign_check(expr, type, qual, 0, 0, 1)) {
+ case CheckResult0:
+ return 0;
+ case CheckResult1:
+ match->x4++;
+ break;
+ case CheckResult2:
+ match->x6++;
+ break;
+ case CheckResult3:
+ match->x8++;
+ match->xA += assign_value;
+ break;
+ case CheckResult4:
+ match->xE++;
+ match->match5.x0 += user_std_match.x0;
+ match->match5.x2 += user_std_match.x2;
+ match->match5.x4 += user_std_match.x4;
+ match->match5.x6 += user_std_match.x6;
+ match->match5.x8 += user_std_match.x8;
+ break;
+ default:
+#line 1585
+ CError_FATAL();
+ }
+
+ if (IS_TYPE_POINTER_ONLY(type))
+ CExpr_MatchCV(expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual, match);
+
+ return 1;
+}
+
+static short CExpr_StdMatchCompare(Match5 *a, Match5 *b, Boolean flag) {
+ if (a->x0 > b->x0) return 1;
+ if (a->x0 == b->x0) {
+ if (a->x2 > b->x2) return 1;
+ if (a->x2 == b->x2) {
+ if (a->x4 > b->x4) return 1;
+ if (a->x4 == b->x4) {
+ if (a->x6 > b->x6) return 1;
+ if (a->x6 == b->x6) {
+ if (!flag)
+ return 0;
+ if (a->x8 > b->x8) return 1;
+ if (a->x8 == b->x8) return 0;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+static short CExpr2_MemberPointerConversion(Type *type, ENode *expr, Boolean flag1) {
+ // returns CheckResult
+}
+
+ENode *CExpr_ClassPointerCast(BClassList *cls, ENode *origexpr, Boolean nullcheckflag) {
+ ENode *expr;
+ ClassList *base;
+ Boolean do_nullcheck;
+ TypeClass *tclass;
+ SInt32 offset;
+ ENode *tmp;
+
+ expr = origexpr;
+ tclass = TYPE_CLASS(cls->type);
+ do_nullcheck = 0;
+#line 1691
+ CError_ASSERT(cls);
+
+ if (!IS_TYPE_POINTER_ONLY(origexpr->rtype)) {
+ CError_Error(CErrorStr141);
+ return origexpr;
+ }
+
+ cls = cls->next;
+ while (cls) {
+ for (base = tclass->bases; base; base = base->next) {
+ if (base->base == TYPE_CLASS(cls->type))
+ break;
+ }
+
+ if (!base) {
+ CError_Error(CErrorStr221);
+ while (cls->next)
+ cls = cls->next;
+
+ tmp = nullnode();
+ tmp->rtype = CDecl_NewPointerType(cls->type);
+ return tmp;
+ }
+
+ if (base->is_virtual) {
+ if (!base->base->sominfo) {
+ do_nullcheck = 1;
+ if ((offset = base->offset) && !canadd(expr, offset)) {
+ expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD);
+ optimizecomm(expr);
+ }
+ expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base)));
+ expr = makemonadicnode(expr, EINDIRECT);
+ }
+ } else {
+ if ((offset = base->offset)) {
+ do_nullcheck = 1;
+ if (!canadd(expr, offset)) {
+ expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD);
+ optimizecomm(expr);
+ }
+ }
+ }
+
+ switch (expr->type) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ expr = makemonadicnode(expr, ETYPCON);
+ }
+
+ expr->rtype = CDecl_NewPointerType(TYPE(base->base));
+ tclass = TYPE_CLASS(cls->type);
+ cls = cls->next;
+ }
+
+ if (nullcheckflag && do_nullcheck)
+ expr = do_castnullcheck(expr, origexpr);
+ return expr;
+}
+
+ENode *CExpr_GetClassAccessNode(BClassList *a, BClassList *b, ENode *expr, Object *obj, AccessType access, Boolean flag) {
+ TypeClass *tclass;
+ ENode *tmp;
+
+ if (!expr) {
+ if (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func || !(expr = CClass_CreateThisSelfExpr())) {
+ CError_Error(CErrorStr221);
+ return NULL;
+ }
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->rtype = TYPE(cscope_currentclass);
+ }
+
+#line 1786
+ CError_ASSERT(a);
+#line 1787
+ CError_ASSERT(IS_TYPE_CLASS(expr->rtype));
+
+ tclass = TYPE_CLASS(expr->rtype);
+ a = CScope_GetClassAccessPath(a, tclass);
+ if (!a || a->type != TYPE(tclass)) {
+ CError_Error(CErrorStr221);
+ return NULL;
+ }
+
+ if (flag)
+ CClass_CheckPathAccess(a, obj, access);
+
+ if (!TYPE_CLASS(a->type)->sominfo) {
+ if (b)
+ a = CClass_AppendPath(a, b);
+
+ if (!ENODE_IS(expr, EINDIRECT))
+ expr = CExpr_LValue(expr, 0, 0);
+
+ if (ENODE_IS(expr, EINDIRECT)) {
+ expr->data.monadic->flags = expr->flags;
+ tmp = expr->data.monadic;
+ switch (tmp->type) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ tmp = makemonadicnode(tmp, ETYPCON);
+ }
+ expr = makemonadicnode(CExpr_ClassPointerCast(a, tmp, 0), EINDIRECT);
+ expr->rtype = TYPE(tclass);
+ }
+ }
+
+ return expr;
+}
+
+static short std_assign_check_overload(NameSpaceObjectList *list, TemplArg *templargs, Type *type, Boolean flag1) {
+}
+
+ENode *CExpr_ConvertToBool(ENode *expr, Boolean flag) {
+ if (IS_TYPE_MEMBERPOINTER(expr->rtype))
+ expr = CExpr_ConvertToCondition(expr);
+
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ case TYPEPOINTER:
+ if (IS_TYPE_ENUM(expr->rtype))
+ expr = forceintegral(expr);
+ switch (expr->type) {
+ case EINTCONST:
+ CInt64_SetLong(&expr->data.intval, !CInt64_IsZero(&expr->data.intval));
+ break;
+ case EFLOATCONST:
+ CInt64_SetLong(&expr->data.intval, !CMach_FloatIsZero(expr->data.floatval));
+ expr->type = EINTCONST;
+ break;
+ default:
+ expr = makemonadicnode(expr, ELOGNOT);
+ expr->rtype = TYPE(&stbool);
+ expr = makemonadicnode(expr, ELOGNOT);
+ }
+ break;
+ default:
+ CError_Error(
+ flag ? CErrorStr247 : CErrorStr209,
+ expr->rtype,
+ expr->flags & ENODE_FLAG_QUALS,
+ &stbool,
+ 0);
+ expr = nullnode();
+ }
+
+ expr->rtype = TYPE(&stbool);
+ return expr;
+}
+
+static short std_assign_check(ENode *expr, Type *type, Boolean flag1, Boolean flag2) {
+ short result;
+
+ if (copts.cplusplus) {
+ illegalimplicitconversion = 0;
+
+ if ((result = iscpp_typeequal(expr->rtype, type))) {
+ assign_node = expr;
+ if (result == -1) {
+ assign_value = 1;
+ return CheckResult3;
+ } else {
+ return CheckResult1;
+ }
+ }
+
+ if (flag1 && illegalimplicitconversion) {
+ CError_Error(CErrorStr209, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0);
+ return CheckResult0;
+ }
+ } else {
+ if (is_typeequal(expr->rtype, type)) {
+ assign_node = expr;
+ return CheckResult1;
+ }
+ }
+
+ if (type == TYPE(&stbool)) {
+ switch (expr->rtype->type) {
+ case TYPEPOINTER:
+ case TYPEMEMBERPOINTER:
+ assign_value = 0;
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ if (flag1)
+ assign_node = CExpr_ConvertToBool(expr, 0);
+ return CheckResult3;
+ default:
+ return CheckResult0;
+ }
+ }
+
+ if (IS_TYPE_ENUM(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) {
+ result = CheckResult3;
+ if (IS_TYPE_INT(type)) {
+ if (TYPE_ENUM(expr->rtype)->enumtype == type) {
+ result = CheckResult2;
+ } else if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) {
+ switch (TYPE_INTEGRAL(type)->integral) {
+ case IT_INT:
+ if (expr->rtype->size < stsignedint.size || TYPE_ENUM(expr->rtype)->enumtype == TYPE(&stsignedshort))
+ result = CheckResult2;
+ break;
+ case IT_UINT:
+ if (expr->rtype->size >= stsignedint.size && TYPE_ENUM(expr->rtype)->enumtype != TYPE(&stsignedshort))
+ result = CheckResult2;
+ break;
+ }
+ }
+ }
+ if (flag1) {
+ expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
+ assign_node = promote(expr, type);
+ }
+ return result;
+ }
+
+ if (IS_TYPE_INT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) {
+ result = CheckResult3;
+ if (TYPE_INTEGRAL(expr->rtype)->integral <= IT_INT) {
+ if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) {
+ switch (TYPE_INTEGRAL(type)->integral) {
+ case IT_INT:
+ if (expr->rtype->size < stsignedint.size || type != TYPE(&stunsignedshort))
+ result = CheckResult2;
+ break;
+ case IT_UINT:
+ if (expr->rtype->size == stsignedint.size && type == TYPE(&stunsignedshort))
+ result = CheckResult2;
+ break;
+ }
+ }
+ }
+
+ if (flag1 && type != expr->rtype)
+ assign_node = promote(expr, type);
+ else
+ assign_node = expr;
+ return result;
+ }
+
+ if (IS_TYPE_FLOAT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) {
+ if (type == TYPE(&stdouble) && (expr->rtype == TYPE(&stfloat) || expr->rtype == TYPE(&stshortdouble)))
+ result = CheckResult2;
+ else
+ result = CheckResult3;
+
+ if (flag1 && (!IS_TYPE_FLOAT(type) || type->size != expr->rtype->size))
+ assign_node = promote(expr, type);
+ else
+ assign_node = expr;
+ return result;
+ }
+
+ if (IS_TYPE_POINTER_ONLY(type)) {
+ if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval) && (IS_TYPE_INT(expr->rtype) || (!copts.cplusplus && IS_TYPE_ENUM(expr->rtype)))) {
+ if (flag1)
+ expr->rtype = TYPE(&stunsignedlong);
+ assign_node = expr;
+ return CheckResult3;
+ }
+ if (ENODE_IS(expr, EOBJLIST)) {
+ return std_assign_check_overload(expr->data.objlist.list, expr->data.objlist.templargs, type, flag1);
+ }
+ if (IS_TYPE_POINTER_ONLY(expr->rtype)) {
+ if (ENODE_IS(expr, EOBJREF) && IS_TYPE_FUNC(expr->data.objref->type) && (TYPE_FUNC(expr->data.objref->type)->flags & FUNC_FLAGS_100000)) {
+ NameSpaceObjectList list;
+ list.next = NULL;
+ list.object = OBJ_BASE(expr->data.objref);
+ return std_assign_check_overload(&list, NULL, type, flag1);
+ }
+ if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type)) {
+ assign_value = 1;
+ return CheckResult3;
+ }
+ if (IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) {
+ short depth;
+ Boolean isambig;
+ BClassList *path;
+ path = CClass_GetBasePath(
+ TYPE_CLASS(TYPE_POINTER(expr->rtype)->target),
+ TYPE_CLASS(TYPE_POINTER(type)->target),
+ &depth, &isambig
+ );
+ if (path) {
+ assign_value = 1000 - depth;
+ if (flag1) {
+ if (isambig)
+ CError_Error(CErrorStr188);
+ if (flag2)
+ CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC);
+ assign_node = CExpr_ClassPointerCast(path, expr, 1);
+ }
+ return CheckResult3;
+ } else {
+ if (flag1) {
+ if (isambig)
+ CError_Error(CErrorStr188);
+ else
+ CError_Error(
+ CErrorStr244,
+ expr->rtype,
+ expr->flags & ENODE_FLAG_QUALS,
+ type,
+ 0);
+ }
+ return CheckResult0;
+ }
+ }
+ }
+ }
+
+ if (IS_TYPE_MEMBERPOINTER(type) && !IS_TYPE_CLASS(expr->rtype)) {
+ return CExpr2_MemberPointerConversion(type, expr, flag1);
+ }
+
+ if (IS_TYPE_CLASS(expr->rtype) && IS_TYPE_CLASS(type)) {
+ short depth;
+ Boolean isambig;
+ BClassList *path;
+ path = CClass_GetBasePath(
+ TYPE_CLASS(expr->rtype),
+ TYPE_CLASS(type),
+ &depth, &isambig
+ );
+ if (path) {
+ assign_value = 1000 - depth;
+ if (flag1) {
+ if (isambig)
+ CError_Error(CErrorStr188);
+ CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC);
+ assign_node = getnodeaddress(expr, 0);
+ assign_node = CExpr_ClassPointerCast(path, assign_node, 0);
+ assign_node = makemonadicnode(assign_node, EINDIRECT);
+ assign_node->rtype = type;
+ }
+ return CheckResult3;
+ }
+ }
+
+ if (IS_TYPE_ENUM(type)) {
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ if (!copts.cplusplus) {
+ if (flag1) {
+ if (copts.pedantic)
+ CError_Warning(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0);
+ assign_node = do_typecast(expr, type, 0);
+ assign_node->flags = expr->flags;
+ }
+ return CheckResult2;
+ } else {
+ if (flag1)
+ CError_Error(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0);
+ }
+ }
+ }
+
+ return CodeGen_AssignCheck(expr, type, flag1, flag2);
+}
+
+static short is_compatible_conversion(Type *a, Type *b) {
+ if (IS_TYPE_REFERENCE(a))
+ a = TYPE_POINTER(a)->target;
+ if (IS_TYPE_REFERENCE(b))
+ b = TYPE_POINTER(b)->target;
+ return iscpp_typeequal(b, a);
+}
+
+static void CExpr_ConIteratorInit(ConIterator *iter) {
+ ClassList *base;
+ ConIterator *subiter;
+ ConIteratorList *list;
+
+ for (base = iter->tclass->bases; base; base = base->next) {
+ if (base->base->flags & CLASS_FLAGS_40) {
+ subiter = galloc(sizeof(ConIterator));
+ memclrw(subiter, sizeof(ConIterator));
+ subiter->parent = iter;
+ subiter->tclass = base->base;
+ CExpr_ConIteratorInit(subiter);
+
+ list = galloc(sizeof(ConIteratorList));
+ memclrw(list, sizeof(ConIteratorList));
+ list->iter = subiter;
+ list->next = iter->children;
+ iter->children = list;
+ }
+ }
+}
+
+void CExpr_ConversionIteratorInit(ConversionIterator *iter, TypeClass *tclass) {
+ memclrw(iter, sizeof(ConversionIterator));
+ if (tclass->flags & CLASS_FLAGS_40) {
+ iter->coniter = &iter->myconiter;
+ iter->myconiter.tclass = tclass;
+ CExpr_ConIteratorInit(&iter->myconiter);
+ CScope_InitObjectIterator(&iter->objiter, tclass->nspace);
+ }
+}
+
+static Boolean CExpr_ConversionIteratorIsHidden(ConIterator *iter, TypeFunc *tfunc) {
+ CScopeObjectIterator objiter;
+ ObjBase *obj;
+ TypeFunc *objtfunc;
+
+ while (iter) {
+ CScope_InitObjectIterator(&objiter, iter->tclass->nspace);
+ while (1) {
+ if (!(obj = CScope_NextObjectIteratorObject(&objiter)))
+ break;
+
+ objtfunc = TYPE_FUNC(OBJECT(obj)->type);
+ if (
+ IS_TYPE_FUNC(objtfunc) &&
+ (objtfunc->flags & FUNC_FLAGS_40) &&
+ is_compatible_conversion(tfunc->functype, objtfunc->functype) &&
+ (tfunc->args->qual & Q_CONST) == (objtfunc->args->qual & Q_CONST) &&
+ (tfunc->qual & Q_CONST) == (objtfunc->qual & Q_CONST)
+ )
+ return 1;
+ }
+ iter = iter->parent;
+ }
+
+ return 0;
+}
+
+Object *CExpr_ConversionIteratorNext(ConversionIterator *iter) {
+ ConIterator *ci;
+ Object *obj;
+
+ ci = iter->coniter;
+ if (!ci)
+ return NULL;
+
+restart:
+ if ((obj = OBJECT(CScope_NextObjectIteratorObject(&iter->objiter)))) {
+ if (
+ IS_TYPE_FUNC(obj->type) &&
+ (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_40) &&
+ !CExpr_ConversionIteratorIsHidden(ci->parent, TYPE_FUNC(obj->type))
+ ) {
+ return obj;
+ }
+ goto restart;
+ }
+
+ do {
+ if (ci->children) {
+ iter->coniter = ci->children->iter;
+ ci->children = ci->children->next;
+ ci = iter->coniter;
+ CScope_InitObjectIterator(&iter->objiter, ci->tclass->nspace);
+ goto restart;
+ }
+ } while ((ci = ci->parent));
+
+ return NULL;
+}
+
+void user_assign_check() {}
+
+ENode *CExpr_ConvertToCondition(ENode *expr) {
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ return expr;
+ case TYPEENUM:
+ expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
+ return expr;
+ case TYPEMEMBERPOINTER:
+ return memberpointercompare(ENOTEQU, expr, nullnode());
+ case TYPECLASS:
+ return CExpr_Convert(expr, TYPE(&stbool), 0, 0, 1);
+ default:
+ CError_Error(376, expr->rtype, expr->flags & ENODE_FLAG_QUALS);
+ return nullnode();
+ }
+}
+
+void CExpr_ConvertToIntegral() {}
+void CExpr_CheckArithmConversion() {}
+void get_address_of_temp_copy() {}
+
+short assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) {
+}
+
+void CExpr_MatchCompare() {}
+static void MatchOverloadFunc() {}
+void CExpr_GetFuncMatchArgs() {}
+
+static NameSpaceObjectList *CExpr_CopyNameSpaceObjectList(NameSpaceObjectList *list) {
+ NameSpaceObjectList *first;
+ NameSpaceObjectList *work;
+
+ first = work = lalloc(sizeof(NameSpaceObjectList));
+ while (1) {
+ work->object = list->object;
+ list = list->next;
+ if (!list) {
+ work->next = NULL;
+ break;
+ } else {
+ work->next = lalloc(sizeof(NameSpaceObjectList));
+ work = work->next;
+ }
+ }
+ return first;
+}
+
+static void CExpr_MatchArgList() {}
+
+ENode *CExpr_GetDefaultArgument(ENode *funcexpr, FuncArg *arg) {
+ ENode *tmp;
+
+ if (CTemplTool_IsTemplateArgumentDependentExpression(arg->dexpr)) {
+#line 3264
+ CError_ASSERT(ENODE_IS(funcexpr, EOBJREF));
+ tmp = CTemplTool_DeduceDefaultArg(
+ funcexpr->data.objref,
+ CInline_CopyExpression(arg->dexpr, CopyMode0)
+ );
+ return argumentpromotion(tmp, arg->type, arg->qual, 1);
+ }
+
+ return CInline_CopyExpression(arg->dexpr, CopyMode0);
+}
+
+static ENode *CExpr_GenericCall(ENode *funcexpr, ENodeList *argexprs, TypeFunc *tfunc, FuncArg *args) {
+ ENodeList *list;
+ ENode *callexpr;
+
+ while (args) {
+ if (args->dexpr) {
+ if (argexprs) {
+ list = argexprs;
+ while (list->next)
+ list = list->next;
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ } else {
+ list = argexprs = lalloc(sizeof(ENodeList));
+ }
+ list->next = NULL;
+ list->node = CExpr_GetDefaultArgument(funcexpr, args);
+ }
+ args = args->next;
+ }
+
+ callexpr = lalloc(sizeof(ENode));
+ callexpr->type = EFUNCCALL;
+ callexpr->cost = 4;
+ callexpr->rtype = tfunc->functype;
+ callexpr->flags = tfunc->qual & ENODE_FLAG_QUALS;
+ callexpr->data.funccall.funcref = funcexpr;
+ callexpr->data.funccall.funcref->rtype = CDecl_NewPointerType(TYPE(tfunc));
+ callexpr->data.funccall.args = argexprs;
+ callexpr->data.funccall.functype = tfunc;
+ funcexpr->data.objref->flags |= OBJECT_FLAGS_UNUSED;
+ return CExpr_AdjustFunctionCall(callexpr);
+}
+
+static Boolean CExpr_IsObjrefPlusX(ENode *expr) {
+ Type *type;
+
+ if (ENODE_IS(expr, EOBJREF)) {
+ type = expr->data.objref->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ return IS_TYPE_CLASS(type);
+ }
+
+ if (ENODE_IS2(expr, EADD, ESUB)) {
+ if (CExpr_IsObjrefPlusX(expr->data.diadic.left))
+ return 1;
+ if (CExpr_IsObjrefPlusX(expr->data.diadic.right))
+ return 1;
+ }
+
+ return 0;
+}
+
+static Boolean CExpr_IsStaticType(ENode *expr) {
+ return ENODE_IS(expr, EINDIRECT) && CExpr_IsObjrefPlusX(expr->data.monadic);
+}
+
+ENode *CExpr_VarArgPromotion(ENode *expr, Boolean flag) {
+ if (!copts.old_argmatch)
+ expr = pointer_generation(expr);
+
+ switch (expr->rtype->type) {
+ case TYPEVOID:
+ case TYPEFUNC:
+ CError_Error(CErrorStr353);
+ expr = nullnode();
+ break;
+ case TYPEINT:
+ case TYPEENUM:
+ expr = integralpromote(expr);
+ break;
+ case TYPEFLOAT:
+ if (TYPE_INTEGRAL(expr->rtype)->integral < IT_DOUBLE)
+ expr = promote(expr, TYPE(&stdouble));
+ break;
+ case TYPECLASS:
+ expr = classargument(expr);
+ break;
+ }
+
+ if (!flag && copts.warn_largeargs) {
+ if ((IS_TYPE_INT(expr->rtype) && TYPE_INTEGRAL(expr->rtype)->integral >= IT_LONGLONG) || IS_TYPE_FLOAT(expr->rtype))
+ CError_Warning(CErrorStr316);
+ }
+
+ return expr;
+}
+
+void CExpr_GenericFuncCall() {}
+void CExpr_GenericPtmfCall() {}
+static void CExpr_ConvertEMember() {}
+void CExpr_MakeFunctionCall() {}
+static void accept_conversion_type() {}
+static void CExpr_OperatorConversion() {}
+static void wild_conversion_check() {}
+static void monadic_conversion_check() {}
+static void is_legal_type_combination() {}
+static void match_class_type_conversion() {}
+static void match_type_class_conversion() {}
+static void match_class_class_conversion() {}
+void CExpr_CheckOperatorConversion() {}
+void CExpr_CheckOperator() {}
+
+ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *args, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4, Boolean flag5) {
+ ENode *expr;
+ Object *ctor;
+
+#line 4595
+ CError_ASSERT(IS_TYPE_POINTER_ONLY(addr_expr->rtype));
+
+ addr_expr = makemonadicnode(addr_expr, EINDIRECT);
+ addr_expr->rtype = TYPE(tclass);
+
+ if (!flag3 && args && !args->next && args->node->rtype == TYPE(tclass) && !CClass_CopyConstructor(tclass)) {
+#line 4605
+ CError_ASSERT(IS_TYPE_CLASS(addr_expr->rtype));
+ expr = makediadicnode(addr_expr, args->node, EASS);
+ if (!flag1)
+ expr = getnodeaddress(expr, 0);
+ return expr;
+ }
+
+ if ((ctor = CClass_Constructor(tclass))) {
+ if (tclass->flags & CLASS_FLAGS_20) {
+ ENodeList *list = lalloc(sizeof(ENodeList));
+ list->next = args;
+ args = list;
+ list->node = intconstnode(TYPE(&stsignedshort), flag2 != 0);
+ }
+ // TODO: 12CE80 call to genericfunccall
+ } else {
+ if (args) {
+ if (!args->next && ENODE_IS(addr_expr, EINDIRECT)) {
+ return makediadicnode(
+ addr_expr,
+ CExpr_AssignmentPromotion(args->node, TYPE(tclass), 0, 1),
+ EASS);
+ }
+ CError_Error(174);
+ }
+ return addr_expr;
+ }
+}
+
+static void CExpr_DeleteFuncCall() {}
+static void CExpr_CopyPlacementNewArg() {}
+static void CExpr_PlacementDeleteCall() {}
+static void scan_type_name() {}
+static void cv_qualifier_list() {}
+static void scan_new_declarator() {}
+static void scan_new_type_name() {}
+static void CExpr_NewAlloc() {}
+static void CExpr_NewExceptionSafeAlloc() {}
+static void CExpr_NewExceptionSafeInit() {}
+static void CExpr_NewArray() {}
+static void CExpr_NewSimpleClass() {}
+static void CExpr_NewClass() {}
+void scannew() {}
+static void CExpr_DeleteArray() {}
+void scandelete() {}
diff --git a/compiler_and_linker/unsorted/CFunc.c b/compiler_and_linker/unsorted/CFunc.c
new file mode 100644
index 0000000..76d880a
--- /dev/null
+++ b/compiler_and_linker/unsorted/CFunc.c
@@ -0,0 +1,105 @@
+#include "compiler/CFunc.h"
+#include "compiler/types.h"
+
+FuncArg elipsis;
+FuncArg oldstyle;
+ObjectList *arguments;
+ObjectList *locals;
+short localcount;
+SInt32 curstmtvalue;
+SInt32 sourceoffset;
+HashNameNode *sourcefilepath;
+SInt32 functionbodyoffset;
+HashNameNode *functionbodypath;
+InitExpr *init_expressions;
+CLabel *Labels;
+CtorChain *ctor_chain;
+Statement *curstmt;
+static short temp_destructor_object_regmem;
+static short temp_destructor_objects;
+static short temp_expression_has_conditionals;
+static DeclBlock *firstblock;
+static DeclBlock *currentblock;
+static short blockcount;
+static Object *sinit_first_object;
+static CLabel *sinit_label;
+static Boolean ainit_only_one;
+static ENode *ainit_expr;
+static FuncArg *check_arglist;
+static Boolean cfunc_is_extern_c;
+static short cfunc_staticvarcount;
+static void *destroyobjects;
+static Boolean cfunc_hasdtortemp;
+
+static void CFunc_LoopIncrement(void) {}
+static void CFunc_LoopDecrement(void) {}
+DeclBlock *CFunc_NewDeclBlock(void) {}
+void CFunc_RestoreBlock(DeclBlock *block) {}
+void CFunc_SetupLocalVarInfo(Object *obj) {}
+static void adjustargumenttype(DeclInfo *declinfo) {}
+static FuncArg *CFunc_IsInArgList(FuncArg *list, HashNameNode *name) {}
+static Object *CFunc_IsInObjList(ObjectList *list, HashNameNode *name) {}
+static void CFunc_AppendArg(FuncArg **list, FuncArg *arg) {}
+static void identifier_list(DeclInfo *declinfo) {}
+static Boolean defarg_name_obj_check(HashNameNode *name, Object *obj) {}
+void CFunc_DefaultArg(Type *type, short qual, FuncArg *args) {}
+static FuncArg *parameter_list(DeclInfo *declinfo) {}
+Boolean CFunc_ParseFakeArgList(Boolean flag) {}
+FuncArg *parameter_type_list(DeclInfo *declinfo) {}
+CLabel *findlabel(void) {}
+CLabel *newlabel(void) {}
+Statement *CFunc_AppendStatement(StatementType sttype) {}
+Statement *CFunc_InsertStatement(StatementType sttype, Statement *after) {}
+Statement *CFunc_InsertBeforeStatement(StatementType sttype, Statement *before) {}
+void CheckCLabels(void) {}
+Object *create_temp_object(Type *type) {}
+ENode *create_temp_node(Type *type) {}
+ENode *create_temp_node2(Type *type) {}
+static void CFunc_DestroyReverse() {} // not sure about type
+static void CFunc_TempTransDestroy() {} // not sure about type
+void CFunc_WarnUnused(void) {}
+void CFunc_CodeCleanup(Statement *stmt) {}
+static Boolean DestructorNeeded(ExceptionAction *a, ExceptionAction *b) {}
+static Statement *DestructLocals(Statement *stmt, ExceptionAction *exc1, ExceptionAction *exc2) {}
+static Boolean NeedsDestruction(Statement *stmt1, Statement *stmt2) {}
+static ExceptionAction *FindLastNonCommonStackObj(Statement *stmt1, Statement *stmt2) {}
+static void DestructorReturnTransform(Statement *stmt1, Statement *stmt2) {}
+static Statement *DestructorIfTransform(Statement *stmt) {}
+static Boolean IsSubStack(ExceptionAction *exc1, ExceptionAction *exc2) {}
+static void CFunc_CheckInitSkip(Statement *stmt, ExceptionAction *exc) {}
+void CFunc_DestructorCleanup(Statement *stmt) {}
+static void scancase(DeclThing *thing) {}
+static void CFunc_NameLocalStaticDataObject(Object *obj, char *str) {}
+static void sinit_insert_expr(ENode *expr) {}
+static void ainit_insert_expr(ENode *expr) {}
+static ENode *ainit_register_object(TypeClass *tclass, Object *local, SInt32 offset, void *unk) {}
+static void CFunc_LocalDataDeclarator(DeclInfo *declinfo, TStreamElement *element, Boolean flag1, Boolean flag2) {}
+static ENode *CFunc_ParseLocalDeclarationList(Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) {}
+static void makeifstatement(ENode *expr, CLabel *label1, CLabel *label2, Boolean flag1, Boolean flag2) {}
+static void CFunc_HasDtorTempCallBack(ENode *expr) {}
+static void ifstatement(Boolean flag1, ENode *expr, CLabel *label, Boolean flag2) {}
+Statement *CFunc_GenerateLoop(Statement *stmt, Type *type, ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, ENode (*callback)(ENode *, ENode *)) {}
+static Boolean checklabel(void) {}
+static ENode *returnstatementadjust(ENode *expr, Type *type, UInt32 qual) {}
+static void CFunc_AutoResultCheck(ENode *expr) {}
+static void statement(DeclThing *thing) {}
+void CFunc_CompoundStatement(DeclThing *thing) {}
+static void CFunc_InsertArgumentCopyConversion(Object *obj, Type *type1, Type *type2, Boolean flag) {}
+static void CFunc_AdjustOldStyleArgs(void) {}
+void CFunc_SetupNewFuncArgs(Object *obj, FuncArg *args) {}
+static ObjectList *CFunc_CopyObjectList(ObjectList *list) {}
+static void SetupFunctionArguments(Object *obj, DeclInfo *declinfo) {}
+NameSpace *CFunc_FuncGenSetup(Statement *stmt) {}
+void CFunc_GetGlobalCompilerState(CFuncSave *state) {}
+void CFunc_SetGlobalCompilerState(CFuncSave *state) {}
+void CFunc_Gen(Statement *stmt, Object *obj, UInt8 unk) {}
+static void CFunc_CheckCtorInitializer(TypeClass *tclass, CtorChain *chain) {}
+void CFunc_CheckClassCtors(TypeClass *tclass) {}
+static void CFunc_ParseCtorInitializer(void) {}
+static void CFunc_FunctionRedefinedCheck(Object *obj) {}
+static Object *CFunc_DeclareFuncName(char *str, HashNameNode *name) {}
+void CFunc_ParseFuncDef(Object *obj, DeclInfo *declinfo, TypeClass *tclass, Boolean is_method, Boolean is_static, NameSpace *nspace) {}
+void InitExpr_Register(ENode *expr, Object *object) {}
+void CFunc_GenerateDummyFunction(Object *a) {}
+void CFunc_GenerateSingleExprFunc(Object *a, ENode *expr) {}
+void CFunc_GenerateDummyCtorFunc(Object *a, Object *b) {}
diff --git a/compiler_and_linker/unsorted/CInit.c b/compiler_and_linker/unsorted/CInit.c
new file mode 100644
index 0000000..a305c38
--- /dev/null
+++ b/compiler_and_linker/unsorted/CInit.c
@@ -0,0 +1,3107 @@
+#include "compiler/CInit.h"
+#include "compiler/CABI.h"
+#include "compiler/CClass.h"
+#include "compiler/CDecl.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CInline.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/CScope.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+// TODO - move me!!
+extern void PreComp_StaticData(Object *obj, void *data, OLinkList *list, SInt32 size);
+extern void ObjGen_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size);
+extern void ObjGen_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size);
+extern void CExcept_RegisterDestructorObject(Object *obj, SInt32 offset, Object *dtor, Boolean flag);
+extern void CExcept_RegisterLocalArray(Statement *stmt, Object *obj, Object *dtor, SInt32 count, SInt32 size);
+
+TempNodeCB cinit_tempnodefunc;
+InitInfo *cinit_initinfo;
+static PooledString *cinit_stringlist;
+static PooledString *cinit_pooledstringlist;
+static PooledString *cinit_pooledwstringlist;
+static ObjectList *cinit_tentative;
+static TypeClass *cinit_loop_class;
+static ENodeList *cinit_fdtnode;
+static Boolean cinit_fdtambig;
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct CInit_1C {
+ struct CInit_1C *next;
+ Type *type;
+ ENode *expr;
+ SInt32 offset;
+} CInit_1C;
+
+typedef struct CInit_Stuff {
+ struct CInit_Stuff *x0;
+ struct CInit_Stuff *x4;
+ char *buffer;
+ SInt32 xC;
+ SInt32 size;
+ SInt32 bufferSize;
+ SInt32 x18;
+ CInit_1C *x1C;
+ OLinkList *list;
+ Boolean flag;
+} CInit_Stuff;
+
+typedef enum {
+ Stage0,
+ Stage1,
+ Stage2,
+ Stage3,
+ Stage4
+} Stage;
+
+typedef struct CInit_Stuff2 {
+ ENode *expr;
+ ENode myexpr;
+ Stage stage;
+ Boolean x23;
+ SInt32 x24;
+ Type *type;
+} CInit_Stuff2;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+// forward decls
+static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean flag);
+static void CInit_Type(Type *type, UInt32 qual, Boolean flag);
+
+void CInit_Init(void) {
+ cinit_tempnodefunc = NULL;
+ cinit_initinfo = NULL;
+ cinit_stringlist = NULL;
+ cinit_pooledstringlist = NULL;
+ cinit_pooledwstringlist = NULL;
+ cinit_tentative = NULL;
+}
+
+static void CInit_SetupInitInfo(InitInfo *info, Object *obj) {
+ memclrw(info, sizeof(InitInfo));
+ info->obj = obj;
+ info->next = cinit_initinfo;
+ cinit_initinfo = info;
+}
+
+static void CInit_CleanupInitInfo(InitInfo *info) {
+ cinit_initinfo = info->next;
+}
+
+static void CInit_SetupInitInfoBuffer(Type *type) {
+ SInt32 size = type->size;
+ cinit_initinfo->size = size;
+
+ if (!size)
+ size = 512;
+ else if (size & 1)
+ size++;
+
+ cinit_initinfo->buffer = lalloc(size);
+ cinit_initinfo->bufferSize = size;
+ memclrw(cinit_initinfo->buffer, size);
+}
+
+static void CInit_SetData(void *data, SInt32 offset, SInt32 size) {
+ SInt32 end;
+ char *buffer;
+
+ end = offset + size;
+ if (end > cinit_initinfo->size)
+ cinit_initinfo->size = end;
+
+ if (end > cinit_initinfo->bufferSize) {
+ if (cinit_initinfo->obj->type->size == 0) {
+ if (end < 8000)
+ end += 0x400;
+ else
+ end += 0x4000;
+ }
+ if (end & 1)
+ end++;
+
+ buffer = lalloc(end);
+ memclrw(buffer, end);
+ memcpy(buffer, cinit_initinfo->buffer, cinit_initinfo->bufferSize);
+ cinit_initinfo->buffer = buffer;
+ cinit_initinfo->bufferSize = end;
+ }
+
+ if (data)
+ memcpy(cinit_initinfo->buffer + offset, data, size);
+}
+
+typedef struct CInit_Initializer {
+ struct CInit_Initializer *next;
+ struct CInit_Initializer *sublist;
+ ENode *expr;
+ TStreamElement element;
+} CInit_Initializer;
+
+static CInit_Initializer *CInit_ParseInitializerList(void) {
+ CInit_Initializer *r30;
+ CInit_Initializer *r29;
+ CInit_Initializer *tmp;
+
+ if ((tk = lex()) == '}')
+ return NULL;
+
+ r30 = NULL;
+ do {
+ if (r30) {
+ tmp = lalloc(sizeof(CInit_Initializer));
+ r29->next = tmp;
+ r29 = tmp;
+ }
+ if (!r30) {
+ r30 = r29 = lalloc(sizeof(CInit_Initializer));
+ }
+ r29->next = NULL;
+
+ if (tk == '{') {
+ r29->element = *CPrep_CurStreamElement();
+ r29->sublist = CInit_ParseInitializerList();
+ r29->expr = NULL;
+ tk = lex();
+ } else {
+ r29->sublist = NULL;
+ r29->expr = conv_assignment_expression();
+ r29->element = *CPrep_CurStreamElement();
+ }
+
+ if (tk == '}')
+ return r30;
+
+ if (tk != ',') {
+ CError_Error(116);
+ return r30;
+ }
+ } while ((tk = lex()) != '}');
+
+ return r30;
+}
+
+static CInit_Initializer *CInit_ParseInitializerClause(void) {
+ CInit_Initializer *init;
+
+ init = lalloc(sizeof(CInit_Initializer));
+ init->next = NULL;
+ if (tk != '{') {
+ init->sublist = NULL;
+ init->expr = conv_assignment_expression();
+ init->element = *CPrep_CurStreamElement();
+ } else {
+ init->element = *CPrep_CurStreamElement();
+ init->expr = NULL;
+ init->sublist = CInit_ParseInitializerList();
+ tk = lex();
+ }
+
+ return init;
+}
+
+static ENode *CInit_ParseInitializer(ENode *expr) {
+ CInt64 save_int;
+ Float save_float;
+ SInt32 save_size;
+ short t;
+
+ switch (tk) {
+ case TK_INTCONST:
+ case TK_FLOATCONST:
+ save_int = tkintconst;
+ save_float = tkfloatconst;
+ save_size = tksize;
+ t = lookahead();
+ tkintconst = save_int;
+ tkfloatconst = save_float;
+ tksize = save_size;
+
+ switch (t) {
+ case ',':
+ case ';':
+ case '}':
+ memclrw(expr, sizeof(ENode));
+ switch (tk) {
+ case TK_INTCONST:
+ expr->type = EINTCONST;
+ expr->rtype = atomtype();
+ expr->data.intval = tkintconst;
+ break;
+ case TK_FLOATCONST:
+ expr->type = EFLOATCONST;
+ expr->rtype = atomtype();
+ expr->data.floatval = tkfloatconst;
+ break;
+ }
+ tk = lex();
+ CPrep_TokenStreamFlush();
+ return expr;
+ }
+ }
+
+ expr = assignment_expression();
+ CPrep_TokenStreamFlush();
+ return expr;
+}
+
+static Stage CInit_ParseNextInit(CInit_Stuff2 *s) {
+ DeclInfo di;
+ short t;
+
+ s->expr = NULL;
+ if (tk == ';') {
+ s->stage = Stage4;
+ return Stage4;
+ }
+ switch (s->stage) {
+ case Stage0:
+ if (s->x23) {
+ if (tk == '(') {
+ tk = lex();
+ CParser_GetDeclSpecs(&di, 1);
+ s->type = di.thetype;
+ if (tk == ')')
+ tk = lex();
+ else
+ CError_Error(115);
+
+ if (tk == '(')
+ tk = lex();
+ else
+ CError_Error(114);
+ s->x24++;
+ t = lookahead();
+ if (t == TK_UU_VECTOR || (t == TK_IDENTIFIER && !strcmp("vector", tkidentifier->name)))
+ CInit_ParseNextInit(s);
+ s->stage = Stage1;
+ return Stage1;
+ }
+ } else {
+ if (tk == '{') {
+ tk = lex();
+ s->x24 = 0;
+ s->stage = Stage1;
+ return Stage1;
+ }
+ }
+ s->expr = CInit_ParseInitializer(&s->myexpr);
+ s->stage = Stage2;
+ return Stage2;
+ case Stage1:
+ break;
+ case Stage2:
+ case Stage3:
+ if (tk == ',') {
+ tk = lex();
+ break;
+ }
+ if (s->x24) {
+ if (tk != ')')
+ CError_Error(174);
+ if (s->x24 > 1) {
+ s->x24--;
+ tk = lex();
+ CInit_ParseNextInit(s);
+ }
+ } else {
+ if (tk != '}')
+ CError_Error(174);
+ }
+ s->stage = Stage3;
+ return Stage3;
+ default:
+#line 389
+ CError_FATAL();
+ }
+
+ switch (tk) {
+ case '{':
+ tk = lex();
+ s->stage = Stage1;
+ return Stage1;
+ case '}':
+ s->stage = Stage3;
+ return Stage3;
+ case '(':
+ if (s->x23) {
+ tk = lex();
+ s->stage = Stage1;
+ return Stage1;
+ }
+ case ')':
+ if (s->x23 && s->x24) {
+ if (s->x24 > 1) {
+ s->x24--;
+ tk = lex();
+ CInit_ParseNextInit(s);
+ }
+ s->stage = Stage3;
+ return Stage3;
+ }
+ default:
+ s->expr = CInit_ParseInitializer(&s->myexpr);
+ s->stage = Stage2;
+ return Stage2;
+ }
+}
+
+static void CInit_CloseInitList(void) {
+ if (tk == ',' && copts.cplusplus)
+ tk = lex();
+
+ if (tk != '}')
+ CError_ErrorSkip(130);
+ else
+ tk = lex();
+}
+
+static Boolean CInit_IsAllZero(char *buf, SInt32 size) {
+ SInt32 i;
+
+ if (copts.explicit_zero_data)
+ return 0;
+
+ for (i = 0; i < size; i++)
+ if (buf[i]) return 0;
+
+ return 1;
+}
+
+static Boolean CInit_ClassNeedsConstruction(TypeClass *tclass) {
+ return CClass_Constructor(tclass) || CClass_Destructor(tclass);
+}
+
+static Boolean CInit_IsSimpleStructArrayInit(Type *type) {
+ switch (type->type) {
+ case TYPESTRUCT:
+ return 1;
+ case TYPEARRAY:
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (!IS_TYPE_CLASS(type))
+ return 1;
+ case TYPECLASS:
+ return !CInit_ClassNeedsConstruction(TYPE_CLASS(type));
+ default:
+ return 0;
+ }
+}
+
+static Boolean CInit_IsSimpleInit(Type *type) {
+ switch (type->type) {
+ case TYPEPOINTER:
+ return (TYPE_POINTER(type)->qual & Q_REFERENCE) == 0;
+ case TYPEARRAY:
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (!IS_TYPE_CLASS(type))
+ return 1;
+ case TYPECLASS:
+ return !CInit_ClassNeedsConstruction(TYPE_CLASS(type));
+ default:
+ return 1;
+ }
+}
+
+static Object *CInit_GetInitObject(Object *obj) {
+ if (obj->datatype == DALIAS) {
+#line 521
+ CError_ASSERT(!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() {
+ return CDecl_NewStructType(void_ptr.size * 3, CMach_GetTypeAlign((Type *) &void_ptr));
+}
+
+static Object *CInit_CreateStaticData(Type *type) {
+ Object *obj = CInit_CreateStaticDataObject(type, 0, NULL);
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ return obj;
+}
+
+static void CInit_InitNonConst(CInit_Stuff *s, Type *type, ENode *expr) {
+ CInit_1C *entry;
+ CInit_1C *scan;
+ MWVector128 *vec;
+
+ if (s->x4->flag || IS_TYPE_VECTOR(type)) {
+ if (IS_TYPE_VECTOR(type) && ENODE_IS(expr, EVECTOR128CONST)) {
+ vec = (MWVector128 *) (s->buffer + s->size);
+ *vec = expr->data.vector128val;
+ CMach_InitVectorMem(type, *vec, vec, 1);
+ }
+
+ entry = lalloc(sizeof(CInit_1C));
+ memclrw(entry, sizeof(CInit_1C));
+ entry->next = NULL;
+ entry->type = type;
+ entry->expr = expr;
+ entry->offset = s->xC + s->size;
+ if ((scan = s->x4->x1C)) {
+ while (scan->next)
+ scan = scan->next;
+ scan->next = entry;
+ } else {
+ s->x4->x1C = entry;
+ }
+ } else {
+ CError_Error(124);
+ }
+}
+
+static CInit_Stuff *CInit_GrowBuffer(CInit_Stuff *s, SInt32 size) {
+ CInit_Stuff *newbuf;
+
+ newbuf = lalloc(sizeof(CInit_Stuff));
+ memclrw(newbuf, sizeof(CInit_Stuff));
+ newbuf->x4 = s->x4;
+ newbuf->buffer = lalloc(size);
+ newbuf->xC = s->xC + s->size;
+ newbuf->bufferSize = size;
+ s->x0 = newbuf;
+ memset(newbuf->buffer, 0, newbuf->bufferSize);
+ return newbuf;
+}
+
+Boolean CInit_RelocInitCheck(ENode *expr, Object **objptr, CInt64 *valptr, Boolean flag) {
+ Object *objcheck1;
+ Object *objcheck2;
+ CInt64 valcheck1;
+ CInt64 valcheck2;
+
+ *objptr = NULL;
+ valptr->lo = 0;
+ valptr->hi = 0;
+
+ while (1) {
+ switch (expr->type) {
+ case EINTCONST:
+ *valptr = expr->data.intval;
+ return 1;
+ case EOBJREF:
+ objcheck1 = CInit_GetInitObject(expr->data.objref);
+ if (objcheck1->datatype == DLOCAL && !flag)
+ return 0;
+ *objptr = objcheck1;
+ return 1;
+ case ESTRINGCONST:
+ CInit_RewriteString(expr, 0);
+ continue;
+ case ETYPCON:
+ do {
+ if (expr->rtype->size != expr->data.monadic->rtype->size)
+ return 0;
+ expr = expr->data.monadic;
+ if (!IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_INT(expr->rtype))
+ return 0;
+ } while (ENODE_IS(expr, ETYPCON));
+ continue;
+ case EADD:
+ if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag))
+ return 0;
+ if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag))
+ return 0;
+
+ if (objcheck1) {
+ if (objcheck2)
+ return 0;
+ *objptr = objcheck1;
+ } else {
+ *objptr = objcheck1;
+ }
+
+ *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '+', valcheck2);
+ return 1;
+ case ESUB:
+ if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag))
+ return 0;
+ if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag))
+ return 0;
+
+ if (objcheck2)
+ return 0;
+
+ *objptr = objcheck1;
+ *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '-', valcheck2);
+ return 1;
+ default:
+ return 0;
+ }
+ }
+}
+
+static void CInit_InitTypePointer(CInit_Stuff *s, ENode *expr, TypePointer *tptr, UInt32 qual) {
+ Object *obj;
+ CInt64 val;
+ OLinkList *list;
+
+ expr = CExpr_AssignmentPromotion(expr, TYPE(tptr), qual & (Q_CONST | Q_VOLATILE), 1);
+ if (IS_TYPE_POINTER_ONLY(expr->rtype) || ENODE_IS(expr, EINTCONST)) {
+ if (CInit_RelocInitCheck(expr, &obj, &val, 0)) {
+ if (obj) {
+ list = lalloc(sizeof(OLinkList));
+ list->next = s->x4->list;
+ list->obj = obj;
+ list->somevalue = CInt64_GetULong(&val);
+ list->offset = s->xC + s->size;
+ s->x4->list = list;
+ } else {
+ CMach_InitIntMem(TYPE(&stunsignedlong), val, s->buffer + s->size);
+ }
+ } else {
+ CInit_InitNonConst(s, TYPE(tptr), expr);
+ }
+ } else {
+ CError_Error(174);
+ }
+}
+
+static void CInit_InitTypeInt(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) {
+ expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1);
+ if (IS_TYPE_INT(expr->rtype)) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ CMach_InitIntMem(TYPE(tint), expr->data.intval, s->buffer + s->size);
+ } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSI_strict)) {
+ CInit_InitTypePointer(s, expr->data.monadic, TYPE_POINTER(expr->data.monadic->rtype), qual);
+ } else {
+ CInit_InitNonConst(s, TYPE(tint), expr);
+ }
+ } else {
+ CError_Error(174);
+ }
+}
+
+static void CInit_InitTypeFloat(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) {
+ expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1);
+ if (IS_TYPE_FLOAT(expr->rtype)) {
+ if (ENODE_IS(expr, EFLOATCONST)) {
+ CMach_InitFloatMem(TYPE(tint), expr->data.floatval, s->buffer + s->size);
+ } else {
+ CInit_InitNonConst(s, TYPE(tint), expr);
+ }
+ } else {
+ CError_Error(174);
+ }
+}
+
+static void CInit_InitTypeEnum(CInit_Stuff *s, ENode *expr, TypeEnum *tenum, UInt32 qual) {
+ expr = CExpr_AssignmentPromotion(expr, TYPE(tenum), qual & (Q_CONST | Q_VOLATILE), 1);
+ if (IS_TYPE_ENUM(expr->rtype)) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ CMach_InitIntMem(tenum->enumtype, expr->data.intval, s->buffer + s->size);
+ } else {
+ CInit_InitNonConst(s, TYPE(tenum), expr);
+ }
+ } else {
+ CError_Error(174);
+ }
+}
+
+static void CInit_InitTypeMemberPointer(CInit_Stuff *s, ENode *expr, TypeMemberPointer *tmptr, UInt32 qual) {
+ expr = CExpr_AssignmentPromotion(expr, TYPE(tmptr), qual & (Q_CONST | Q_VOLATILE), 1);
+ if (ENODE_IS(expr, EINTCONST)) {
+ CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, s->buffer + s->size);
+ } else {
+ CInit_InitNonConst(s, TYPE(tmptr), expr);
+ }
+}
+
+static void CInit_SetBitfield(TypeBitfield *tbitfield, UInt8 *buffer, CInt64 val) {
+ int i;
+ int pos;
+ int step;
+
+ if (copts.little_endian) {
+ pos = tbitfield->unkA;
+ step = 1;
+ } else {
+ pos = tbitfield->unkB + tbitfield->unkA - 1;
+ step = -1;
+ }
+ for (i = 0; i < tbitfield->unkB; i++) {
+ if (CInt64_GetULong(&val) & 1) {
+ if (copts.little_endian) {
+ buffer[pos >> 3] |= 1 << (pos & 7);
+ } else {
+ buffer[pos >> 3] |= 0x80 >> (pos & 7);
+ }
+ }
+ val = CInt64_ShrU(val, cint64_one);
+ pos += step;
+ }
+}
+
+static void CInit_InitTypeBitfield(CInit_Stuff *s, ENode *expr, TypeBitfield *tbitfield, UInt32 qual) {
+ Type *inner;
+
+ inner = tbitfield->bitfieldtype;
+ if (IS_TYPE_ENUM(inner))
+ inner = TYPE_ENUM(inner)->enumtype;
+ expr = CExpr_AssignmentPromotion(expr, inner, qual & (Q_CONST | Q_VOLATILE), 1);
+
+ if (IS_TYPE_INT(expr->rtype)) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ CInit_SetBitfield(tbitfield, (UInt8 *) s->buffer + s->size, expr->data.intval);
+ } else {
+ CInit_InitNonConst(s, TYPE(tbitfield), expr);
+ }
+ } else {
+ CError_Error(174);
+ }
+}
+
+static void CInit_InitTypeArray(CInit_Stuff *s, CInit_Stuff2 *s2, TypePointer *tptr, UInt32 qual, Boolean errorflag) {
+ SInt32 targetsize;
+ SInt32 start;
+ SInt32 i;
+ Boolean flag;
+ Boolean is_zero_size;
+ SInt32 size;
+ SInt32 tmp;
+ Boolean is_char_ptr;
+ Boolean is_wchar_ptr;
+
+ is_zero_size = tptr->size == 0;
+ targetsize = tptr->target->size;
+ if (!targetsize) {
+ CError_Error(145);
+ return;
+ }
+
+ is_char_ptr = IS_TYPE_INT(tptr->target) && (targetsize == 1);
+ is_wchar_ptr = IS_TYPE_INT(tptr->target) && (targetsize == stwchar.size);
+ switch (s2->stage) {
+ case Stage1:
+ flag = 1;
+ if (CInit_ParseNextInit(s2) == Stage3) {
+ if (is_zero_size)
+ CError_Error(174);
+ tk = lex();
+ return;
+ }
+ break;
+ case Stage2:
+ flag = 0;
+ break;
+ }
+ switch (s2->stage) {
+ case Stage1:
+ case Stage2:
+ break;
+ default:
+ CError_Error(174);
+ return;
+ }
+
+ if (s2->stage == Stage2)
+ s2->expr = pointer_generation(s2->expr);
+
+ if (s2->stage == Stage2 && ENODE_IS(s2->expr, ESTRINGCONST) && (is_char_ptr || is_wchar_ptr)) {
+ if (IS_TYPE_POINTER_ONLY(s2->expr->rtype) && tptr->target->size != TYPE_POINTER(s2->expr->rtype)->target->size)
+ CError_Warning(174);
+ size = tmp = s2->expr->data.string.size;
+ if (is_zero_size) {
+ tptr->size = s2->expr->data.string.size;
+ if (s->bufferSize < tmp)
+ s = CInit_GrowBuffer(s, tmp);
+ memcpy(s->buffer, s2->expr->data.string.data, size);
+ s->size = size;
+ } else {
+ if (s2->expr->data.string.size > tptr->size) {
+ if (copts.cplusplus || (s2->expr->data.string.size - 1) > tptr->size)
+ CError_Error(147);
+ s2->expr->data.string.size = tptr->size;
+ size = tptr->size;
+ }
+ memcpy(s->buffer + s->size, s2->expr->data.string.data, size);
+ }
+ } else {
+ if (!flag && errorflag) {
+ CError_Error(174);
+ return;
+ }
+
+ start = s->size;
+ i = 0;
+ while (1) {
+ if (is_zero_size) {
+ size = (i + 1) * targetsize;
+ s->size = start + size - targetsize - s->xC;
+ if (s->size + targetsize > s->bufferSize)
+ s = CInit_GrowBuffer(s, targetsize * 16);
+ CInit_InitType(s, s2, tptr->target, qual, 0);
+ tptr->size = size;
+ s->size = start + size - s->xC;
+ } else {
+ if (tptr->size <= i * targetsize) {
+ i--;
+ CError_Error(147);
+ }
+ s->size = start + i * targetsize;
+ CInit_InitType(s, s2, tptr->target, qual, 0);
+ if (!flag && tptr->size <= (i + 1) * targetsize)
+ break;
+ }
+
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage1:
+ case Stage2:
+ break;
+ case Stage3:
+ if (flag)
+ tk = lex();
+ return;
+ default:
+ CError_Error(130);
+ return;
+ }
+
+ i++;
+ }
+ }
+
+ if (flag) {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage3:
+ tk = lex();
+ return;
+ case Stage2:
+ CError_Error(147);
+ return;
+ default:
+ CError_Error(130);
+ }
+ }
+}
+
+static void CInit_InitTypeStruct(CInit_Stuff *s, CInit_Stuff2 *s2, 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(145);
+ return;
+ }
+
+ switch (s2->stage) {
+ case Stage1:
+ flag = 1;
+ if (CInit_ParseNextInit(s2) == Stage3) {
+ tk = lex();
+ return;
+ }
+ break;
+ case Stage2:
+ flag = 0;
+ break;
+ }
+
+ switch (s2->stage) {
+ case Stage1:
+ case Stage2:
+ break;
+ default:
+ CError_Error(174);
+ return;
+ }
+
+ if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tstruct))) {
+ s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tstruct), qual, 1);
+ if (IS_TYPE_STRUCT(s2->expr->rtype))
+ CInit_InitNonConst(s, TYPE(tstruct), s2->expr);
+ return;
+ }
+
+ start = s->size;
+ while (1) {
+ s->size = start + member->offset;
+ if (!member->type->size) {
+ if (!errorflag || !IS_TYPE_ARRAY(member->type)) {
+ CError_Error(147);
+ if (!IS_TYPE_ARRAY(member->type))
+ return;
+ }
+
+ arraytype = *TYPE_POINTER(member->type);
+ CInit_InitTypeArray(s, s2, &arraytype, member->qual, 1);
+ s->x18 = arraytype.size;
+ } else {
+ CInit_InitType(s, s2, member->type, member->qual, 0);
+ }
+
+ count++;
+ if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr) {
+#line 1218
+ CError_ASSERT(!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(147);
+ return;
+ default:
+ CError_Error(130);
+ return;
+ }
+ }
+ return;
+ } else {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage1:
+ case Stage2:
+ continue;
+ case Stage3:
+ if (flag)
+ tk = lex();
+ if (IS_TYPESTRUCT_VECTOR(tstruct)) {
+ switch (TYPE_STRUCT(tstruct)->stype) {
+ case STRUCT_TYPE_4:
+ case STRUCT_TYPE_5:
+ case STRUCT_TYPE_6:
+ if (count != 16) {
+ if (count == 1) {
+ UInt8 val, *p;
+ p = (UInt8 *) s->buffer;
+ val = p[0];
+ for (i = 1; i < 16; i++)
+ p[i] = val;
+ } else {
+ CError_Error(174);
+ }
+ }
+ break;
+ case STRUCT_TYPE_7:
+ case STRUCT_TYPE_8:
+ case STRUCT_TYPE_9:
+ case STRUCT_TYPE_E:
+ if (count != 8) {
+ if (count == 1) {
+ SInt16 val, *p;
+ p = (SInt16 *) s->buffer;
+ val = p[0];
+ for (i = 1; i < 8; i++)
+ p[i] = val;
+ } else {
+ CError_Error(174);
+ }
+ }
+ break;
+ case STRUCT_TYPE_A:
+ case STRUCT_TYPE_B:
+ case STRUCT_TYPE_C:
+ case STRUCT_TYPE_D:
+ if (count != 4) {
+ if (count == 1) {
+ UInt32 val, *p;
+ p = (UInt32 *) s->buffer;
+ val = p[0];
+ for (i = 1; i < 4; i++)
+ p[i] = val;
+ } else {
+ CError_Error(174);
+ }
+ }
+ break;
+ }
+ }
+ return;
+ default:
+ CError_Error(174);
+ return;
+ }
+ }
+ }
+}
+
+static ObjMemberVar *CInit_FindNextMember(ObjMemberVar *ivar) {
+ ObjMemberVar *scan = ivar;
+ while (1) {
+ scan = scan->next;
+ if (!scan)
+ return NULL;
+ if (!scan->anonunion)
+ return scan;
+ if (scan->offset > ivar->offset)
+ return scan;
+ if (IS_TYPE_BITFIELD(scan->type) && IS_TYPE_BITFIELD(ivar->type) && TYPE_BITFIELD(scan->type)->unkA != TYPE_BITFIELD(ivar->type)->unkA)
+ return scan;
+ }
+}
+
+static void CInit_InitTypeClass(CInit_Stuff *s, CInit_Stuff2 *s2, TypeClass *tclass, UInt32 qual, Boolean errorflag) {
+ ObjMemberVar *ivar;
+ SInt32 start;
+ Boolean flag;
+ SInt32 last_offset;
+ TypePointer arraytype;
+
+ if (tclass->bases || tclass->vtable) {
+ CError_Error(174);
+ return;
+ }
+
+ switch (s2->stage) {
+ case Stage1:
+ flag = 1;
+ if (CInit_ParseNextInit(s2) == Stage3) {
+ tk = lex();
+ return;
+ }
+ break;
+ case Stage2:
+ flag = 0;
+ break;
+ }
+
+ switch (s2->stage) {
+ case Stage1:
+ case Stage2:
+ break;
+ default:
+ CError_Error(174);
+ return;
+ }
+
+ if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tclass) || CExpr_CanImplicitlyConvert(s2->expr, TYPE(tclass), 0))) {
+ s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tclass), qual, 1);
+ if (IS_TYPE_CLASS(s2->expr->rtype))
+ CInit_InitNonConst(s, TYPE(tclass), s2->expr);
+ return;
+ }
+
+ for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
+ if (ivar->access != ACCESSPUBLIC) {
+ CError_Error(174);
+ break;
+ }
+ }
+
+ if (!(ivar = tclass->ivars)) {
+ CError_Error(147);
+ return;
+ }
+ start = s->size;
+ while (1) {
+ s->size = start + ivar->offset;
+ if (!ivar->type->size) {
+ if (!errorflag || !IS_TYPE_ARRAY(ivar->type)) {
+ CError_Error(147);
+ if (!IS_TYPE_ARRAY(ivar->type))
+ return;
+ }
+
+ arraytype = *TYPE_POINTER(ivar->type);
+ CInit_InitTypeArray(s, s2, &arraytype, ivar->qual, 1);
+ s->x18 = arraytype.size;
+ } else {
+ CInit_InitType(s, s2, ivar->type, ivar->qual, 0);
+ }
+
+ last_offset = ivar->offset;
+ if (!(ivar = CInit_FindNextMember(ivar)) || (tclass->mode == CLASS_MODE_1 && ivar->offset == last_offset)) {
+ if (flag) {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage3:
+ tk = lex();
+ return;
+ case Stage2:
+ CError_Error(147);
+ return;
+ default:
+ CError_Error(130);
+ return;
+ }
+ }
+ return;
+ } else {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage1:
+ case Stage2:
+ continue;
+ case Stage3:
+ if (flag)
+ tk = lex();
+ break;
+ default:
+ CError_Error(174);
+ }
+ return;
+ }
+ }
+}
+
+static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean errorflag) {
+ Boolean flag;
+
+ switch (type->type) {
+ case TYPEVOID:
+ CError_Error(174);
+ break;
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ case TYPEBITFIELD:
+ case TYPEMEMBERPOINTER:
+ case TYPEPOINTER:
+ switch (s2->stage) {
+ case Stage1:
+ flag = 1;
+ CInit_ParseNextInit(s2);
+ break;
+ case Stage2:
+ flag = 0;
+ break;
+ }
+ if (s2->stage != Stage2) {
+ CError_Error(174);
+ return;
+ }
+
+ switch (type->type) {
+ case TYPEINT:
+ CInit_InitTypeInt(s, s2->expr, TYPE_INTEGRAL(type), qual);
+ break;
+ case TYPEFLOAT:
+ CInit_InitTypeFloat(s, s2->expr, TYPE_INTEGRAL(type), qual);
+ break;
+ case TYPEENUM:
+ CInit_InitTypeEnum(s, s2->expr, TYPE_ENUM(type), qual);
+ break;
+ case TYPEPOINTER:
+ CInit_InitTypePointer(s, s2->expr, TYPE_POINTER(type), qual);
+ break;
+ case TYPEMEMBERPOINTER:
+ CInit_InitTypeMemberPointer(s, s2->expr, TYPE_MEMBER_POINTER(type), qual);
+ break;
+ case TYPEBITFIELD:
+ CInit_InitTypeBitfield(s, s2->expr, TYPE_BITFIELD(type), qual);
+ break;
+ default:
+#line 1542
+ CError_FATAL();
+ }
+
+ if (flag) {
+ switch (CInit_ParseNextInit(s2)) {
+ case Stage3:
+ tk = lex();
+ break;
+ case Stage2:
+ CError_Error(147);
+ break;
+ default:
+ CError_Error(130);
+ }
+ }
+ break;
+ case TYPESTRUCT:
+ CInit_InitTypeStruct(s, s2, TYPE_STRUCT(type), qual, errorflag);
+ break;
+ case TYPEARRAY:
+ CInit_InitTypeArray(s, s2, TYPE_POINTER(type), qual, errorflag);
+ break;
+ case TYPECLASS:
+ CInit_InitTypeClass(s, s2, TYPE_CLASS(type), qual, errorflag);
+ break;
+ default:
+#line 1573
+ CError_FATAL();
+ }
+}
+
+static void CInit_InitData(CInit_Stuff *s, Type *type, UInt32 qual, Boolean flag) {
+ CInit_Stuff2 s2;
+ SInt32 size;
+ CInit_Stuff *tmp;
+ char *buffer;
+
+ locklheap();
+ memclrw(s, sizeof(CInit_Stuff));
+ s->x4 = s;
+ if (type->size == 0) {
+ if (IS_TYPE_ARRAY(type))
+ s->bufferSize = 16 * TYPE_POINTER(type)->target->size;
+ else
+ CError_Error(145);
+ } else {
+ s->bufferSize = type->size;
+ }
+
+ s->buffer = lalloc(s->bufferSize);
+ memset(s->buffer, 0, s->bufferSize);
+ s->flag = flag;
+
+ s2.stage = Stage0;
+ s2.x23 = 0;
+ if (IS_TYPE_VECTOR(type)) {
+ s2.x23 = 1;
+ s->flag = 1;
+ }
+ if (IS_TYPE_ARRAY(type) && IS_TYPE_VECTOR(TYPE_POINTER(type)->target)) {
+ s->flag = 1;
+ }
+
+ s2.type = NULL;
+ s2.x24 = 0;
+ CInit_ParseNextInit(&s2);
+ CInit_InitType(s, &s2, type, qual, 1);
+
+ if ((size = type->size + s->x18)) {
+ if (s->x0) {
+ buffer = lalloc(size);
+ for (tmp = s; tmp; tmp = tmp->x0) {
+#line 1647
+ CError_ASSERT((tmp->xC + tmp->size) <= size);
+ memcpy(buffer + tmp->xC, tmp->buffer, tmp->size);
+ }
+ s->buffer = buffer;
+ }
+ } else {
+ CError_Error(174);
+ }
+
+ s->size = size;
+ s->x0 = NULL;
+ unlocklheap();
+}
+
+static ENode *CInit_InitConcat(ENode *a1, ENode *a2, SInt32 offset, Type *type, ENode *a5) {
+ ENode *r30;
+ ENode *r28;
+ ENode *tmp;
+
+ r28 = lalloc(sizeof(ENode));
+ *r28 = *a2;
+ if (offset)
+ r28 = makediadicnode(r28, intconstnode(TYPE(&stunsignedlong), offset), EADD);
+
+ if (IS_TYPE_BITFIELD(type)) {
+ tmp = makemonadicnode(r28, EBITFIELD);
+ tmp->rtype = type;
+ tmp = makemonadicnode(tmp, EINDIRECT);
+ tmp->rtype = TYPE_BITFIELD(type)->bitfieldtype;
+ } else {
+ tmp = makemonadicnode(r28, EINDIRECT);
+ tmp->rtype = type;
+ }
+
+ r30 = makediadicnode(tmp, a5, EASS);
+ if (!a1) {
+ return r30;
+ } else {
+ tmp = makediadicnode(a1, r30, ECOMMA);
+ tmp->rtype = r30->rtype;
+ return tmp;
+ }
+}
+
+static ENode *CInit_RegisterDtorObject(Type *type, Object *dtor, ENode *objexpr) {
+ ENode *expr;
+
+ if (copts.no_static_dtors)
+ return objexpr;
+
+ expr = lalloc(sizeof(ENode));
+ expr->type = EFUNCCALL;
+ expr->cost = 4;
+ expr->flags = 0;
+ expr->rtype = CDecl_NewPointerType(type);
+ expr->data.funccall.funcref = create_objectrefnode(Xgreg_func);
+ expr->data.funccall.functype = TYPE_FUNC(Xgreg_func->type);
+ expr->data.funccall.args = lalloc(sizeof(ENodeList));
+ expr->data.funccall.args->node = objexpr;
+ expr->data.funccall.args->next = lalloc(sizeof(ENodeList));
+ expr->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, 1));
+ 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) {
+ Object *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(115);
+ } else if (valueexpr) {
+ list = lalloc(sizeof(ENodeList));
+ list->node = valueexpr;
+ list->next = NULL;
+ } else {
+ list = NULL;
+ }
+
+ expr = create_objectrefnode(obj);
+ if (offset)
+ expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD);
+
+ if (ctor) {
+ ctorflag = 1;
+ if (tk == '=') {
+ ctorflag = 0;
+ if (list)
+ CError_Error(174);
+
+ list = lalloc(sizeof(ENodeList));
+ list->next = NULL;
+ tk = lex();
+ list->node = conv_assignment_expression();
+ }
+
+ expr = CExpr_ConstructObject(tclass, expr, list, 0, 1, 0, 1, ctorflag);
+ if (expr->rtype->type != TYPEPOINTER) {
+ CError_Error(174);
+ return 1;
+ }
+ } else {
+ if (list)
+ CError_Error(174);
+ }
+
+ if (dtor)
+ expr = CInit_RegisterDtorObject(TYPE(tclass), dtor, expr);
+
+ if (cinit_initinfo->x16)
+ cinit_initinfo->init_expr_register_cb(expr);
+ else
+ InitExpr_Register(expr, obj);
+
+ return 1;
+}
+
+static Boolean CInit_ConstructAutoObject(TypeClass *tclass, ENode *expr, SInt32 offset, Boolean flag) {
+ ENodeList *r30;
+ ENode *r29;
+ Object *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(115);
+ } else if (expr) {
+ r30 = lalloc(sizeof(ENodeList));
+ r30->node = expr;
+ r30->next = NULL;
+ } else {
+ r30 = NULL;
+ }
+
+ if (ctor) {
+ r24 = 1;
+ if (tk == '=') {
+ if (r30)
+ CError_Error(174);
+ r30 = lalloc(sizeof(ENodeList));
+ r30->next = NULL;
+ tk = lex();
+ r30->node = conv_assignment_expression();
+ r24 = 0;
+ }
+
+ if (!dtor) {
+ r29 = create_objectrefnode(cinit_initinfo->obj1C);
+ if (offset)
+ r29 = makediadicnode(r29, intconstnode(TYPE(&stunsignedlong), offset), EADD);
+ } else {
+ r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0);
+ }
+
+ r29 = CExpr_ConstructObject(tclass, r29, r30, 0, 1, 0, 1, r24);
+ if (!IS_TYPE_POINTER_ONLY(r29->rtype)) {
+ CError_Error(174);
+ return 1;
+ }
+ r29 = makemonadicnode(r29, EINDIRECT);
+ r29->rtype = TYPE_POINTER(r29->rtype)->target;
+ cinit_initinfo->insert_expr_cb(r29);
+ } else {
+ if (r30)
+ CError_Error(174);
+ if (dtor)
+ r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0);
+ cinit_initinfo->insert_expr_cb(r29);
+ }
+
+ return 1;
+}
+
+static void CInit_ExprPointer(TypePointer *tptr, ENode *expr) {
+ Object *obj;
+ CInt64 val;
+ OLinkList *list;
+
+ if (CInit_RelocInitCheck(expr, &obj, &val, 0)) {
+ if (obj) {
+ list = lalloc(sizeof(OLinkList));
+ list->next = cinit_initinfo->list;
+ list->obj = obj;
+ list->somevalue = CInt64_GetULong(&val);
+ list->offset = cinit_initinfo->expr_offset;
+ cinit_initinfo->list = list;
+ } else {
+ CMach_InitIntMem(TYPE(&stunsignedlong), val, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
+ }
+ } else if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(TYPE(tptr), expr, 0);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(124);
+ }
+
+ cinit_initinfo->expr_offset += 4;
+}
+
+static void CInit_ExprInt(TypeIntegral *tint, ENode *expr) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ CMach_InitIntMem(TYPE(tint), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
+ } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSI_strict)) {
+ CInit_ExprPointer(TYPE_POINTER(expr->data.monadic->rtype), expr->data.monadic);
+ } else if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(TYPE(tint), expr, 0);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(124);
+ }
+
+ cinit_initinfo->expr_offset += tint->size;
+}
+
+static void CInit_ExprFloat(TypeIntegral *tint, ENode *expr) {
+ if (ENODE_IS(expr, EFLOATCONST)) {
+ CMach_InitFloatMem(TYPE(tint), expr->data.floatval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
+ } else if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(TYPE(tint), expr, 0);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(124);
+ }
+
+ cinit_initinfo->expr_offset += tint->size;
+}
+
+static void CInit_ExprEnum(TypeEnum *tenum, ENode *expr) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ CMach_InitIntMem(tenum->enumtype, expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
+ } else if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(TYPE(tenum), expr, 0);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(124);
+ }
+
+ cinit_initinfo->expr_offset += tenum->size;
+}
+
+static void CInit_ExprMemberPointer(TypeMemberPointer *tmptr, ENode *expr) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset);
+ } else if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(TYPE(tmptr), expr, 0);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(124);
+ }
+
+ cinit_initinfo->expr_offset += tmptr->size;
+}
+
+static void CInit_TypeExpr(Type *type, ENode *expr) {
+ switch (type->type) {
+ case TYPEINT:
+ CInit_ExprInt(TYPE_INTEGRAL(type), expr);
+ break;
+ case TYPEFLOAT:
+ CInit_ExprFloat(TYPE_INTEGRAL(type), expr);
+ break;
+ case TYPEENUM:
+ CInit_ExprEnum(TYPE_ENUM(type), expr);
+ break;
+ case TYPEPOINTER:
+ CInit_ExprPointer(TYPE_POINTER(type), expr);
+ break;
+ case TYPEMEMBERPOINTER:
+ CInit_ExprMemberPointer(TYPE_MEMBER_POINTER(type), expr);
+ break;
+ case TYPESTRUCT:
+ case TYPECLASS:
+ if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(type, expr, 0);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(124);
+ }
+ break;
+ case TYPEARRAY:
+ CError_Error(174);
+ break;
+ default:
+#line 2082
+ CError_FATAL();
+ }
+}
+
+static void CInit_Bitfield(TypeBitfield *tbitfield) {
+ Boolean r30;
+ ENode *expr;
+ ENode myexpr;
+
+ r30 = tk == '{';
+ if (r30)
+ tk = lex();
+
+ expr = CInit_ParseInitializer(&myexpr);
+ expr = CExpr_AssignmentPromotion(
+ expr,
+ IS_TYPE_ENUM(tbitfield->bitfieldtype) ? TYPE_ENUM(tbitfield->bitfieldtype)->enumtype : tbitfield->bitfieldtype,
+ 0,
+ 1);
+ if (ENODE_IS(expr, EINTCONST))
+ CInit_SetBitfield(tbitfield, (UInt8 *) cinit_initinfo->buffer + cinit_initinfo->expr_offset, expr->data.intval);
+ else
+ CError_Error(124);
+
+ if (r30)
+ CInit_CloseInitList();
+}
+
+static void CInit_Array(TypePointer *tptr, UInt32 qual, Boolean flag) {
+ SInt32 start;
+ SInt32 i;
+ SInt32 targetsize1;
+ SInt32 targetsize2;
+ Boolean in_block;
+ Boolean is_char_ptr;
+ Boolean needs_construction;
+ Boolean is_wchar_ptr;
+
+ targetsize1 = tptr->target->size;
+ targetsize2 = tptr->target->size;
+ if (!tptr->target->size) {
+ if (!IS_TYPE_ARRAY(tptr->target)) {
+ CError_Error(145);
+ return;
+ }
+ targetsize1 = tptr->target->size;
+ targetsize2 = tptr->target->size;
+ if (!tptr->target->size) {
+ CError_Error(145);
+ return;
+ }
+ }
+
+ is_char_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == 1);
+ is_wchar_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == stwchar.size);
+
+ in_block = 1;
+ if (flag && !(tk == TK_STRING && is_char_ptr) && !(tk == TK_STRING_WIDE && is_wchar_ptr)) {
+ if (tk != '{') {
+ CError_ErrorSkip(135);
+ return;
+ }
+ tk = lex();
+ } else {
+ if (tk == '{')
+ tk = lex();
+ else
+ in_block = 0;
+ }
+
+ if ((tk == TK_STRING && is_char_ptr) || (tk == TK_STRING_WIDE && is_wchar_ptr)) {
+ if (tptr->size) {
+ if (tksize > tptr->size) {
+ if (copts.cplusplus || (tksize - (is_wchar_ptr ? stwchar.size : 1)) > tptr->size)
+ CError_Error(147);
+ tksize = tptr->size;
+ }
+ memcpy(cinit_initinfo->buffer + cinit_initinfo->expr_offset, tkstring, tksize);
+ } else {
+ tptr->size = tksize;
+ CInit_SetData(tkstring, cinit_initinfo->expr_offset, tptr->size);
+ }
+ cinit_initinfo->expr_offset += tptr->size;
+ tk = lex();
+ if (in_block)
+ CInit_CloseInitList();
+ return;
+ }
+
+ if (IS_TYPE_CLASS(tptr->target) && CInit_ClassNeedsConstruction(TYPE_CLASS(tptr->target)))
+ needs_construction = 1;
+ else
+ needs_construction = 0;
+
+ start = cinit_initinfo->expr_offset;
+ i = 0;
+ while (1) {
+ if (tk == '}') {
+ innerloop:
+ if (tptr->size) {
+ if (needs_construction) {
+ while (tptr->size > (i * targetsize1)) {
+ cinit_initinfo->expr_offset = start + i * targetsize2;
+ if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(tptr->target, NULL, 1);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(174);
+ }
+ i++;
+ }
+ }
+ } else {
+ tptr->size = i * targetsize1;
+ }
+ cinit_initinfo->expr_offset = start + tptr->size;
+ if (in_block)
+ tk = lex();
+ return;
+ }
+
+ if (!tptr->size) {
+ cinit_initinfo->expr_offset = start + i * targetsize2;
+ CInit_SetData(NULL, cinit_initinfo->expr_offset, targetsize2);
+ if (needs_construction) {
+ if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(174);
+ }
+ } else {
+ CInit_Type(tptr->target, qual, 0);
+ }
+ } else {
+ if (tptr->size <= i * targetsize1) {
+ i--;
+ CError_Error(147);
+ }
+
+ cinit_initinfo->expr_offset = start + i * targetsize2;
+ if (needs_construction) {
+ if (cinit_initinfo->expr_cb) {
+ cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1);
+ cinit_initinfo->expr_cb_called = 1;
+ } else {
+ CError_Error(174);
+ }
+ } else {
+ CInit_Type(tptr->target, qual, 0);
+ }
+
+ if (!in_block) {
+ if (tptr->size <= (i + 1) * targetsize1)
+ return;
+ }
+ }
+
+ if (tk != '}') {
+ if (tk != ',') {
+ CError_ErrorSkip(121);
+ in_block = 0;
+ i++;
+ goto innerloop;
+ }
+ tk = lex();
+ }
+ i++;
+ }
+}
+
+static void CInit_Struct(TypeStruct *tstruct, Boolean flag) {
+ StructMember *member;
+ SInt32 start;
+ Boolean in_block;
+
+ if (!(member = tstruct->members)) {
+ CError_Error(145);
+ return;
+ }
+
+ if (tstruct->stype == STRUCT_TYPE_UNION) {
+ if (tk == '{') {
+ tk = lex();
+ CInit_Type(member->type, member->qual, 0);
+ if (tk == '}')
+ tk = lex();
+ } else {
+ CInit_Type(member->type, member->qual, 0);
+ }
+ return;
+ }
+
+ if (IS_TYPE_VECTOR(tstruct) && tk != '{') {
+ CInit_TypeExpr(TYPE(tstruct), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tstruct), 0, 1));
+ return;
+ }
+
+ if (tk != '{') {
+ if (flag)
+ CError_ErrorSkip(135);
+ in_block = 0;
+ } else {
+ in_block = 1;
+ tk = lex();
+ }
+
+ start = cinit_initinfo->expr_offset;
+ while (1) {
+ if (tk == '}')
+ break;
+
+ cinit_initinfo->expr_offset = start + member->offset;
+ if (!member->type->size && IS_TYPE_ARRAY(member->type)) {
+ CError_Error(147);
+ break;
+ }
+
+ CInit_Type(member->type, member->qual, 0);
+ if (tk == '}')
+ break;
+
+ if (tk != ',') {
+ CError_Error(121);
+ break;
+ }
+
+ do {
+ member = member->next;
+ } while (member && (member->qual & Q_OVERLOAD));
+
+ if (!member) {
+ if (!in_block)
+ break;
+ if ((tk = lex()) != '}') {
+ CError_Error(147);
+ break;
+ }
+ } else {
+ tk = lex();
+ }
+ }
+
+ cinit_initinfo->expr_offset = start + tstruct->size;
+ if (tk == '}' && in_block)
+ tk = lex();
+}
+
+static void CInit_Class(TypeClass *tclass, Boolean flag) {
+ ObjMemberVar *ivar;
+ SInt32 start;
+ Boolean in_block;
+
+ if (tk == '{') {
+ in_block = 1;
+ tk = lex();
+ } else {
+ in_block = 0;
+ }
+
+ if (tclass->bases || tclass->vtable) {
+ CError_Error(174);
+ return;
+ }
+
+ for (ivar = tclass->ivars; ivar; ivar = ivar->next) {
+ if (ivar->access != ACCESSPUBLIC)
+ break;
+ }
+
+ if (!ivar && !CClass_Constructor(tclass) && (!CClass_Destructor(tclass) || in_block)) {
+ if ((ivar = tclass->ivars)) {
+ start = cinit_initinfo->expr_offset;
+ while (1) {
+ if (tk == '}')
+ break;
+
+ if (!ivar->type->size && IS_TYPE_ARRAY(ivar->type)) {
+ CError_Error(147);
+ break;
+ }
+
+ cinit_initinfo->expr_offset = start + ivar->offset;
+ CInit_Type(ivar->type, ivar->qual, 0);
+
+ if (tk == '}')
+ break;
+
+ if (tk != ',') {
+ CError_Error(121);
+ break;
+ }
+
+ do {
+ ivar = ivar->next;
+ } while (ivar && ivar->anonunion);
+
+ if (!ivar) {
+ if (!in_block)
+ break;
+ if ((tk = lex()) != '}') {
+ CError_Error(147);
+ break;
+ }
+ } else {
+ tk = lex();
+ }
+ }
+ } else {
+ if (in_block && tk != '}')
+ CError_Error(147);
+ }
+ } else {
+ if (in_block)
+ CError_Error(174);
+ CInit_TypeExpr(TYPE(tclass), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tclass), 0, 1));
+ }
+
+ cinit_initinfo->expr_offset = start + tclass->size;
+ if (tk == '}' && in_block)
+ tk = lex();
+}
+
+static void CInit_Type(Type *type, UInt32 qual, Boolean flag) {
+ ENode *expr;
+ ENode myexpr;
+
+ switch (type->type) {
+ case TYPEVOID:
+ CError_Error(174);
+ break;
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ case TYPEPOINTER:
+ case TYPEMEMBERPOINTER:
+ if (tk == '{') {
+ tk = lex();
+ expr = CInit_ParseInitializer(&myexpr);
+ expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1);
+ CInit_CloseInitList();
+ } else {
+ expr = CInit_ParseInitializer(&myexpr);
+ expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1);
+ }
+ CInit_TypeExpr(type, expr);
+ break;
+ case TYPEBITFIELD:
+ CInit_Bitfield(TYPE_BITFIELD(type));
+ break;
+ case TYPEARRAY:
+ CInit_Array(TYPE_POINTER(type), qual, flag);
+ break;
+ case TYPESTRUCT:
+ CInit_Struct(TYPE_STRUCT(type), flag);
+ break;
+ case TYPECLASS:
+ CInit_Class(TYPE_CLASS(type), flag);
+ break;
+ default:
+#line 2482
+ CError_FATAL();
+ }
+}
+
+static void CInit_GlobalStaticInit(Type *type, ENode *valueexpr, Boolean flag) {
+ ENode *expr;
+ ENode *tmp;
+
+ cinit_initinfo->x15 = 1;
+ if (flag) {
+ CInit_ConstructGlobalObject(cinit_initinfo->obj, TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0);
+ } else {
+ expr = create_objectrefnode(cinit_initinfo->obj);
+ if (!IS_TYPE_POINTER_ONLY(expr->rtype)) {
+ CError_Error(174);
+ return;
+ }
+ TYPE_POINTER(expr->rtype)->target = type;
+
+ if (cinit_initinfo->expr_offset)
+ expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD);
+
+ tmp = makemonadicnode(expr, EINDIRECT);
+ tmp->rtype = type;
+ expr = makediadicnode(tmp, valueexpr, EASS);
+ if (cinit_initinfo->x16)
+ cinit_initinfo->init_expr_register_cb(expr);
+ else
+ InitExpr_Register(expr, cinit_initinfo->obj);
+ }
+}
+
+static void CInit_AutoInit(Type *type, ENode *valueexpr, Boolean flag) {
+ ENode *expr;
+ ENode *tmp;
+ Type *copy;
+ SInt32 size;
+
+ if (flag) {
+ CInit_ConstructAutoObject(TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0);
+ } else {
+ if (IS_TYPE_ARRAY(type) && (type->size & 1)) {
+ copy = galloc(sizeof(TypePointer));
+ *TYPE_POINTER(copy) = *TYPE_POINTER(type);
+ type = copy;
+ copy->size = type->size + 1;
+ }
+ expr = create_objectrefnode(cinit_initinfo->obj1C);
+ if (!IS_TYPE_POINTER_ONLY(expr->rtype)) {
+ CError_Error(174);
+ return;
+ }
+ TYPE_POINTER(expr->rtype)->target = type;
+
+ if (cinit_initinfo->expr_offset)
+ expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD);
+
+ tmp = makemonadicnode(expr, EINDIRECT);
+ tmp->rtype = type;
+ expr = makediadicnode(tmp, valueexpr, EASS);
+ if (!copts.cplusplus)
+ CError_Error(124);
+ cinit_initinfo->insert_expr_cb(expr);
+ }
+}
+
+static SInt32 CInit_AdjustObjectDataSize(Object *obj) {
+ if (obj->type->size <= 1)
+ return obj->type->size;
+ if (obj->type->size & 1)
+ return obj->type->size + 1;
+ else
+ return obj->type->size;
+}
+
+static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB expr_cb, Boolean flag) {
+ Object *r31;
+ ENode *expr;
+ ENode *tmpexpr;
+ Type *inner;
+ Type *copy;
+ SInt32 size;
+ Boolean lastflag;
+ SInt16 cv;
+
+ cinit_initinfo->expr_cb = expr_cb;
+ expr = NULL;
+
+ if (tk == '(') {
+ if (IS_TYPE_ARRAY(type))
+ CError_Error(174);
+ tk = lex();
+ expr = CExpr_AssignmentPromotion(assignment_expression(), type, qual, 1);
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+ goto jump_ahead;
+ }
+
+ tk = lex();
+ switch (type->type) {
+ case TYPECLASS:
+ if (tk == '{' && CClass_Constructor(TYPE_CLASS(type)))
+ CError_Error(174);
+ case TYPESTRUCT:
+ if (tk != '{')
+ goto generic_type;
+ case TYPEARRAY:
+ if (!obj) {
+ if (IS_TYPE_ARRAY(type)) {
+ inner = type;
+ while (IS_TYPE_ARRAY(inner))
+ inner = TYPE_POINTER(inner)->target;
+
+ if (IS_TYPE_CLASS(inner) && CInit_ClassNeedsConstruction(TYPE_CLASS(inner))) {
+ CInit_SetupInitInfoBuffer(type);
+ cinit_initinfo->obj = cinit_initinfo->obj1C;
+ CInit_Type(type, cinit_initinfo->obj->qual, 1);
+ return 0;
+ }
+ if (type->size & 1) {
+ copy = galloc(sizeof(TypePointer));
+ *TYPE_POINTER(copy) = *TYPE_POINTER(type);
+ type = copy;
+ type->size++;
+ }
+ }
+
+ obj = CInit_CreateStaticDataObject(type, qual, NULL);
+ cinit_initinfo->obj = obj;
+ expr = create_objectnode(obj);
+ cinit_initinfo->obj1C = obj;
+ }
+ CInit_SetupInitInfoBuffer(type);
+ CInit_Type(type, obj->qual, 1);
+#line 2639
+ CError_ASSERT(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);
+#line 2747
+ CError_ASSERT(obj->type->size == type->size);
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ }
+ return expr;
+ }
+
+ CInit_SetupInitInfoBuffer(type);
+ CInit_TypeExpr(type, expr);
+#line 2756
+ CError_ASSERT(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:
+#line 2776
+ CError_FATAL();
+ }
+
+ 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:
+#line 2807
+ CError_FATAL();
+ }
+
+ 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, 1));
+ else
+ dtor_expr = nullnode();
+
+ stmt->expr = CExpr_FuncCallSix(
+ carr_func,
+ firstarg,
+ create_objectrefnode(ctor),
+ dtor_expr,
+ intconstnode(TYPE(&stunsignedlong), tclass->size),
+ intconstnode(TYPE(&stunsignedlong), count),
+ NULL
+ );
+
+ return stmt;
+}
+
+static void CInit_InitializeClassArray(Object *obj, TypeClass *tclass, Boolean flag) {
+ Object *ctor;
+ Object *dtor;
+ SInt32 count;
+ SInt32 i;
+ ENode *expr;
+ SInt32 offset;
+ ENode *dtor_expr;
+ Statement *stmt;
+ TypeFunc *tfunc;
+ Object *funcobj;
+
+ dtor = CClass_Destructor(tclass);
+ count = obj->type->size / tclass->size;
+ if (CClass_Constructor(tclass)) {
+ ctor = CClass_DefaultConstructor(tclass);
+ if (!ctor) {
+ ctor = CClass_DummyDefaultConstructor(tclass);
+ if (!ctor) {
+ CError_Error(203);
+ return;
+ }
+ }
+ } else {
+ ctor = NULL;
+ }
+
+ if (count <= 1 || (!flag && count <= 8)) {
+ if (flag) {
+ for (i = 0; i < count; i++) {
+ CInit_ConstructGlobalObject(obj, tclass, NULL, i * tclass->size, 0);
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ offset = i * tclass->size;
+ expr = create_objectrefnode(obj);
+ if (offset)
+ expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD);
+ if (ctor)
+ expr = CExpr_ConstructObject(tclass, expr, NULL, 0, 1, 0, 1, 1);
+ cinit_initinfo->insert_expr_cb(expr);
+ if (dtor)
+ CExcept_RegisterDestructorObject(obj, offset, dtor, 1);
+ }
+ if (dtor) {
+ stmt = CFunc_AppendStatement(ST_EXPRESSION);
+ stmt->expr = nullnode();
+ }
+ }
+ } else {
+ if (ctor) {
+ if (!flag && !dtor) {
+ CInit_ConstructClassArray(NULL, tclass, ctor, dtor, create_objectrefnode(obj), count);
+ expr = nullnode();
+ } else {
+ if (dtor)
+ dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, 1));
+ 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, 1)),
+ intconstnode(TYPE(&stsignedlong), tclass->size),
+ intconstnode(TYPE(&stsignedlong), count)
+ ));
+
+ expr = makediadicnode(expr, nullnode(), ECOMMA);
+ expr->rtype = TYPE(&void_ptr);
+
+ expr = funccallexpr(
+ Xgreg_func,
+ expr,
+ create_objectrefnode(funcobj),
+ create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())),
+ NULL
+ );
+ }
+ if (cinit_initinfo->x16)
+ cinit_initinfo->init_expr_register_cb(expr);
+ else
+ InitExpr_Register(expr, obj);
+ } else {
+ stmt = CFunc_AppendStatement(ST_EXPRESSION);
+ stmt->expr = expr;
+ if (dtor) {
+ CExcept_RegisterLocalArray(stmt, obj, dtor, count, tclass->size);
+ stmt = CFunc_AppendStatement(ST_EXPRESSION);
+ stmt->expr = nullnode();
+ }
+ }
+ }
+}
+
+static ENode *CInit_AutoTempNode(Type *type, Boolean flag) {
+ ENode *node;
+ node = CExpr_NewETEMPNode(type, 0);
+ if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type)))
+ node->data.temp.needs_dtor = 1;
+ return node;
+}
+
+static ENode *CInit_GlobalTempNode(Type *type, Boolean flag) {
+ Object *dtor;
+ ENode *node;
+ ENode *funcnode;
+
+ node = create_objectrefnode(CInit_CreateStaticData(type));
+ if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type))) && !copts.no_static_dtors) {
+ if (flag)
+ CError_Error(190);
+
+ funcnode = galloc(sizeof(ENode));
+ funcnode->type = EFUNCCALL;
+ funcnode->cost = 200;
+ funcnode->flags = 0;
+ funcnode->rtype = CDecl_NewPointerType(type);
+ funcnode->data.funccall.funcref = create_objectrefnode(Xgreg_func);
+ funcnode->data.funccall.functype = TYPE_FUNC(Xgreg_func->type);
+ funcnode->data.funccall.args = lalloc(sizeof(ENodeList));
+ funcnode->data.funccall.args->node = node;
+ funcnode->data.funccall.args->next = lalloc(sizeof(ENodeList));
+ funcnode->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, 1));
+ funcnode->data.funccall.args->next->next = lalloc(sizeof(ENodeList));
+ funcnode->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType()));;
+ funcnode->data.funccall.args->next->next->next = NULL;
+ node = funcnode;
+ }
+ return node;
+}
+
+static void CInit_RefInit(Type *type, ENode *expr, Boolean flag) {
+ ENode *objexpr;
+
+ objexpr = create_objectrefnode(cinit_initinfo->obj);
+ if (!IS_TYPE_POINTER_ONLY(objexpr->rtype)) {
+ CError_Error(174);
+ return;
+ }
+ TYPE_POINTER(objexpr->rtype)->target = type;
+
+ if (cinit_initinfo->expr_offset)
+ objexpr = makediadicnode(objexpr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD);
+
+ objexpr = makemonadicnode(objexpr, EINDIRECT);
+ objexpr->rtype = type;
+
+ expr = makediadicnode(objexpr, expr, EASS);
+ if (cinit_initinfo->x16)
+ cinit_initinfo->init_expr_register_cb(expr);
+ else
+ InitExpr_Register(expr, cinit_initinfo->obj);
+}
+
+static Boolean CInit_IsDtorTemp(ENode *expr) {
+ return ENODE_IS(expr, ETEMP) && expr->data.temp.needs_dtor;
+}
+
+static void CInit_FindDtorTemp(ENode *expr) {
+ ENodeList *list;
+
+ while (ENODE_IS(expr, ECOMMA))
+ expr = expr->data.diadic.right;
+
+ if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target)) {
+ switch (expr->type) {
+ case ETYPCON:
+ CInit_FindDtorTemp(expr->data.monadic);
+ break;
+ case EADD:
+ case ESUB:
+ CInit_FindDtorTemp(expr->data.diadic.left);
+ CInit_FindDtorTemp(expr->data.diadic.right);
+ break;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ if ((list = expr->data.funccall.args)) {
+ if (CInit_IsDtorTemp(list->node) || ((list = list->next) && CInit_IsDtorTemp(list->node))) {
+ if (!cinit_fdtnode)
+ cinit_fdtnode = list;
+ else
+ cinit_fdtambig = 1;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void CInit_RefTempTransform(Type *type, ENode *expr) {
+ Object *obj;
+
+#line 3164
+ CError_ASSERT(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) {
+#line 3172
+ CError_ASSERT(!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);
+#line 3213
+ CError_ASSERT(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(115);
+ tk = lex();
+ } else if (tk == '=' && ((tk = lex()) == '{' || IS_TYPE_ARRAY(obj->type))) {
+ insert_cb(CInit_AutoObject(obj, obj->type, obj->qual));
+ return;
+ } else {
+ expr = conv_assignment_expression();
+ }
+ expr = CExpr_AssignmentPromotion(expr, obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1);
+ insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS));
+ } else if (copts.cplusplus && is_const_object(obj)) {
+ CError_Error(224);
+ }
+
+ return;
+ }
+
+ CInit_SetupInitInfo(&initinfo, obj);
+ initinfo.obj1C = obj;
+ initinfo.insert_expr_cb = insert_cb;
+ initinfo.register_object_cb = register_cb;
+
+ if (IS_TYPE_CLASS(obj->type) && CInit_ConstructAutoObject(TYPE_CLASS(obj->type), NULL, 0, 1)) {
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+
+ if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 1)) {
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+
+ if (tk != '=' && (tk != '(' || !copts.cplusplus)) {
+ if (IS_TYPE_ARRAY(obj->type)) {
+ type = obj->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (IS_TYPE_CLASS(type)) {
+ if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) {
+ CInit_InitializeClassArray(obj, TYPE_CLASS(type), 0);
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+ CFunc_CheckClassCtors(TYPE_CLASS(type));
+ }
+ }
+
+ if (IS_TYPE_CLASS(obj->type))
+ CFunc_CheckClassCtors(TYPE_CLASS(obj->type));
+
+ if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus)
+ CError_Error(224);
+ } else {
+ if (obj->type->size || IS_TYPE_ARRAY(obj->type)) {
+ if ((expr = CInit_GenericData(NULL, obj->type, obj->qual, CInit_AutoInit, 0)))
+ insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS));
+ } else {
+ CError_Error(145);
+ }
+ }
+
+ if (IS_TYPE_CLASS(obj->type) && CClass_Destructor(TYPE_CLASS(obj->type)))
+ register_cb(obj->type, obj, 0, NULL);
+
+ CInit_CleanupInitInfo(&initinfo);
+}
+
+void CInit_InitializeStaticData(Object *obj, InitExprRegisterCB cb) {
+ ENode *expr;
+ Type *type;
+ InitInfo initinfo;
+ CInit_Stuff s;
+ CInit_1C *entry;
+ ENode *obj_expr;
+
+ if (CInit_IsSimpleStructArrayInit(obj->type)) {
+ if (tk == '=' || (tk == '(' && copts.cplusplus)) {
+ if (tk == '=')
+ tk = lex();
+ CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus);
+
+ IsCompleteType(obj->type);
+
+ if (!s.x1C && is_const_object(obj))
+ CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size);
+ else
+ CInit_DeclareData(obj, s.buffer, s.list, s.size);
+
+ if (s.x1C) {
+ obj_expr = create_objectrefnode(obj);
+ entry = s.x1C;
+ expr = NULL;
+ while (entry) {
+ expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr);
+ entry = entry->next;
+ }
+ cb(expr);
+ }
+ } else {
+ if (copts.cplusplus && is_const_object(obj))
+ CError_Error(224);
+
+ if (is_const_object(obj))
+ CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size);
+ else
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ }
+ return;
+ }
+
+ CInit_SetupInitInfo(&initinfo, obj);
+ initinfo.x16 = 1;
+ initinfo.init_expr_register_cb = cb;
+
+ if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) {
+ IsCompleteType(obj->type);
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+
+ if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) {
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+
+ if (tk != '=' && (tk != '(' || !copts.cplusplus)) {
+ if (IsCompleteType(obj->type))
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+
+ if (IS_TYPE_ARRAY(obj->type)) {
+ type = obj->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (IS_TYPE_CLASS(type)) {
+ if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) {
+ CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1);
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+ CFunc_CheckClassCtors(TYPE_CLASS(type));
+ }
+ }
+
+ if (IS_TYPE_CLASS(obj->type))
+ CFunc_CheckClassCtors(TYPE_CLASS(obj->type));
+
+ if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus)
+ CError_Error(224);
+ } else {
+ if (obj->type->size || IS_TYPE_ARRAY(obj->type)) {
+ if ((expr = CInit_GenericData(obj, obj->type, obj->qual, CInit_GlobalStaticInit, 1)))
+ cb(makediadicnode(create_objectnode2(obj), expr, EASS));
+ } else {
+ CError_Error(145);
+ }
+ }
+
+ CInit_CleanupInitInfo(&initinfo);
+}
+
+void CInit_InitializeData(Object *obj) {
+ Object *dtor;
+ ObjectList *list;
+ CInt64 val;
+ InitInfo initinfo;
+ Boolean needs_construction;
+ Type *type;
+
+ if (tk == ':') {
+ tk = lex();
+ obj->datatype = DABSOLUTE;
+ val = CExpr_IntegralConstExpr();
+ obj->u.address = CInt64_GetULong(&val);
+ return;
+ }
+
+ if (tk != '=' && (tk != '(' || !copts.cplusplus)) {
+ if (obj->sclass != TK_EXTERN) {
+ if (!copts.cplusplus) {
+ if (IsCompleteType(obj->type)) {
+ for (list = cinit_tentative; list; list = list->next) {
+ if (list->object == obj)
+ break;
+ }
+ if (!list) {
+ list = galloc(sizeof(ObjectList));
+ list->object = obj;
+ list->next = cinit_tentative;
+ cinit_tentative = list;
+ obj->qual |= Q_1000000;
+ }
+ }
+ } else {
+ if (obj->flags & OBJECT_FLAGS_4)
+ CError_Error(329, obj);
+ obj->flags |= OBJECT_FLAGS_4;
+
+ needs_construction = 0;
+ if (IS_TYPE_ARRAY(obj->type)) {
+ type = obj->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+ if (IS_TYPE_CLASS(type)) {
+ if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) {
+ CInit_SetupInitInfo(&initinfo, obj);
+ CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1);
+ CInit_CleanupInitInfo(&initinfo);
+ needs_construction = 1;
+ } else {
+ CFunc_CheckClassCtors(TYPE_CLASS(type));
+ }
+ }
+ } else {
+ if (IS_TYPE_CLASS(obj->type)) {
+ if (CInit_ClassNeedsConstruction(TYPE_CLASS(obj->type))) {
+ CInit_SetupInitInfo(&initinfo, obj);
+ CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 0);
+ CInit_CleanupInitInfo(&initinfo);
+ needs_construction = 1;
+ } else {
+ CFunc_CheckClassCtors(TYPE_CLASS(obj->type));
+ }
+ }
+ }
+
+ if (!needs_construction && copts.cplusplus) {
+ if (IS_TYPE_REFERENCE(obj->type) || is_const_object(obj))
+ CError_Error(224);
+ }
+ if (IsCompleteType(obj->type))
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ }
+ }
+ return;
+ }
+
+ if (obj->flags & OBJECT_FLAGS_4)
+ CError_Error(329, obj);
+
+ if (CInit_IsSimpleStructArrayInit(obj->type)) {
+ if (tk == '=')
+ tk = lex();
+ else
+ CError_Error(121);
+ CInit_GlobalObject(obj);
+ return;
+ }
+
+ CInit_SetupInitInfo(&initinfo, obj);
+ if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) {
+ IsCompleteType(obj->type);
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+
+ if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) {
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+
+ if (obj->type->size == 0 && !IS_TYPE_ARRAY(obj->type)) {
+ CError_Error(145);
+ CInit_CleanupInitInfo(&initinfo);
+ return;
+ }
+
+ if (copts.cplusplus)
+ CInit_GenericData(obj, obj->type, obj->qual, &CInit_GlobalStaticInit, 0);
+ else
+ CInit_GenericData(obj, obj->type, obj->qual, NULL, 0);
+
+ if (IS_TYPE_CLASS(obj->type) && (dtor = CClass_Destructor(TYPE_CLASS(obj->type))))
+ InitExpr_Register(CInit_RegisterDtorObject(obj->type, dtor, create_objectrefnode(obj)), obj);
+
+ CInit_CleanupInitInfo(&initinfo);
+}
+
+Object *CInit_DeclareString(char *data, SInt32 size, Boolean ispascal, Boolean iswide) {
+ PooledString *str;
+ Object *obj;
+ PooledString *scan;
+
+ if (!copts.dont_reuse_strings) {
+ for (scan = cinit_stringlist; scan; scan = scan->next) {
+ if (scan->size == size && scan->ispascal == ispascal && scan->iswide == iswide && !memcmp(scan->data, data, size))
+ return scan->obj;
+ }
+ }
+
+ obj = CParser_NewCompilerDefDataObject();
+ obj->name = CParser_GetUniqueName();
+ if (iswide) {
+ obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size);
+ } else {
+ obj->type = CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size);
+ }
+ obj->sclass = TK_STATIC;
+ CScope_AddGlobalObject(obj);
+
+ if (!iswide && !ispascal && size == (strlen(data) + 1))
+ obj->section = SECT_TEXT_CSTRING;
+ else
+ obj->section = SECT_CONST;
+
+ if (copts.readonly_strings)
+ CInit_DeclareReadOnlyData(obj, data, NULL, obj->type->size);
+ else
+ CInit_DeclareData(obj, data, NULL, obj->type->size);
+
+ str = galloc(sizeof(PooledString));
+ str->next = cinit_stringlist;
+ cinit_stringlist = str;
+ str->obj = obj;
+ str->offset = 0;
+ str->size = size;
+ str->ispascal = ispascal;
+ str->iswide = iswide;
+ str->data = galloc(size);
+ memcpy(str->data, data, size);
+
+ return obj;
+}
+
+PooledString *CInit_DeclarePooledString(char *data, SInt32 size, Boolean ispascal) {
+ PooledString *str;
+ Object *obj;
+ PooledString *scan;
+ SInt32 offset;
+
+ if (!copts.dont_reuse_strings) {
+ for (scan = cinit_pooledstringlist; scan; scan = scan->next) {
+ if (scan->size == size && scan->ispascal == ispascal && !memcmp(scan->data, data, size))
+ return scan;
+ }
+ }
+
+ if (cinit_pooledstringlist) {
+ obj = cinit_pooledstringlist->obj;
+ offset = cinit_pooledstringlist->offset + cinit_pooledstringlist->size;
+ } else {
+ obj = CInit_CreateStaticDataObject(
+ CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size),
+ 0, GetHashNameNodeExport("@stringBase0"));
+ obj->section = SECT_CONST;
+ offset = 0;
+ }
+
+ str = galloc(sizeof(PooledString));
+ str->next = cinit_pooledstringlist;
+ cinit_pooledstringlist = str;
+ str->obj = obj;
+ str->offset = offset;
+ str->size = size;
+ str->ispascal = ispascal;
+ str->data = galloc(size);
+ memcpy(str->data, data, size);
+ return str;
+}
+
+PooledString *CInit_DeclarePooledWString(char *data, SInt32 size) {
+ PooledString *str;
+ Object *obj;
+ PooledString *scan;
+ SInt32 offset;
+
+ if (!copts.dont_reuse_strings) {
+ for (scan = cinit_pooledwstringlist; scan; scan = scan->next) {
+ if (scan->size == size && !memcmp(scan->data, data, size))
+ return scan;
+ }
+ }
+
+ if (cinit_pooledwstringlist) {
+ obj = cinit_pooledwstringlist->obj;
+ offset = cinit_pooledwstringlist->offset + cinit_pooledwstringlist->size;
+ } else {
+ obj = CInit_CreateStaticDataObject(
+ CDecl_NewArrayType(CParser_GetWCharType(), size),
+ 0, GetHashNameNodeExport("@wstringBase0"));
+ obj->section = SECT_CONST;
+ offset = 0;
+ }
+
+ str = galloc(sizeof(PooledString));
+ str->next = cinit_pooledwstringlist;
+ cinit_pooledwstringlist = str;
+ str->obj = obj;
+ str->offset = offset;
+ str->size = size;
+ str->ispascal = 0;
+ str->data = galloc(size);
+ memcpy(str->data, data, size);
+ return str;
+}
+
+void CInit_RewriteString(ENode *expr, Boolean flag) {
+ PooledString *str;
+ Boolean is_wide;
+
+ if (cparamblkptr->isPrecompiling == 1)
+ CError_Error(180);
+
+#line 4220
+ CError_ASSERT(expr->rtype->type == TYPEPOINTER);
+
+ is_wide = TYPE_POINTER(expr->rtype)->target->size != 1;
+ if (copts.pool_strings) {
+ if (is_wide)
+ str = CInit_DeclarePooledWString(expr->data.string.data, expr->data.string.size);
+ else
+ str = CInit_DeclarePooledString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal);
+
+ if (str->offset) {
+ expr->type = EADD;
+ expr->data.diadic.right = intconstnode(TYPE(&stunsignedlong), str->offset);
+ expr->data.diadic.left = create_objectrefnode(str->obj);
+ expr->cost = 1;
+ } else {
+ expr->type = EOBJREF;
+ expr->data.objref = str->obj;
+ }
+ } else {
+ expr->type = EOBJREF;
+ expr->data.objref = CInit_DeclareString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal, is_wide);
+ }
+}
+
+void CInit_DeclarePooledStrings(void) {
+ SInt32 size;
+ char *buffer;
+ PooledString *str;
+
+ size = 0;
+ for (str = cinit_pooledstringlist; str; str = str->next)
+ size += str->size;
+
+ if (size) {
+ cinit_pooledstringlist->obj->type = CDecl_NewArrayType(TYPE(&stchar), size);
+ buffer = galloc(size);
+ for (str = cinit_pooledstringlist; str; str = str->next)
+ memcpy(buffer + str->offset, str->data, str->size);
+
+ if (copts.readonly_strings)
+ CInit_DeclareReadOnlyData(cinit_pooledstringlist->obj, buffer, NULL, size);
+ else
+ CInit_DeclareData(cinit_pooledstringlist->obj, buffer, NULL, size);
+ }
+
+ size = 0;
+ for (str = cinit_pooledwstringlist; str; str = str->next)
+ size += str->size;
+
+ if (size) {
+ cinit_pooledwstringlist->obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size);
+ buffer = galloc(size);
+ for (str = cinit_pooledwstringlist; str; str = str->next)
+ memcpy(buffer + str->offset, str->data, str->size);
+
+ if (copts.readonly_strings)
+ CInit_DeclareReadOnlyData(cinit_pooledwstringlist->obj, buffer, NULL, size);
+ else
+ CInit_DeclareData(cinit_pooledwstringlist->obj, buffer, NULL, size);
+ }
+}
+
+static void declaredata(Object *obj, void *data, OLinkList *list, SInt32 size, Boolean is_readonly) {
+ OLinkList *scan;
+ UInt32 qual;
+
+ qual = obj->qual;
+
+ if (cparamblkptr->isPrecompiling == 1) {
+ PreComp_StaticData(obj, data, list, size);
+ } else {
+ obj->flags |= OBJECT_FLAGS_4;
+ if (!fatalerrors) {
+ for (scan = list; scan; scan = scan->next)
+ CInline_ObjectAddrRef(scan->obj);
+ if (copts.isGeneratingDebugInfo)
+ CPrep_SetSourceFile(&cparser_fileoffset);
+ if (is_readonly)
+ ObjGen_DeclareReadOnlyData(obj, data, list, size);
+ else
+ ObjGen_DeclareData(obj, data, list, size);
+ obj->qual = qual;
+ }
+ }
+}
+
+void CInit_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size) {
+ declaredata(obj, data, list, size, 0);
+}
+
+void CInit_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size) {
+ declaredata(obj, data, list, size, 1);
+}
+
+void CInit_DefineTentativeData(void) {
+ ObjectList *list;
+
+ for (list = cinit_tentative; list; list = list->next) {
+ if (!(list->object->flags & OBJECT_FLAGS_4))
+ CInit_DeclareData(list->object, NULL, NULL, list->object->type->size);
+ }
+
+ cinit_tentative = NULL;
+}
diff --git a/compiler_and_linker/unsorted/CInline.c b/compiler_and_linker/unsorted/CInline.c
new file mode 100644
index 0000000..bd2e46c
--- /dev/null
+++ b/compiler_and_linker/unsorted/CInline.c
@@ -0,0 +1,116 @@
+#include "compiler/CInline.h"
+#include "compiler/CFunc.h"
+
+static CInlineCopyMode enode_copymode;
+static Boolean enode_globalcopy;
+static void *enode_idtrans; // type?
+static void *local_dobjects; // type?
+static void *local_aobjects; // type?
+static CI_Var *loc_args;
+static CI_Var *loc_vars;
+static Boolean inline_expanded;
+static Boolean any_inline_expanded;
+static short cinline_level;
+static void *cinline_label_trans; // type?
+static Statement *cinline_first_stmt;
+static void *cinline_stmtlevelexpr[16]; // type?
+static short cinline_stmtlevelexprs;
+static Boolean cinline_unconditionalpart;
+static Boolean cinline_serialize_stmt;
+static void *cinline_exportlist; // type?
+static CI_Action *cinline_actionlist;
+CI_Action *cinline_tactionlist;
+static ObjectList *cinline_freflist;
+static Boolean cinline_gendeps;
+static Statement *cinline_serial_stmt;
+static Statement *cinline_cur_serial_stmt;
+static void *cinline_uid_temps; // type?
+static Boolean cinline_has_sideeffect;
+static SInt32 inline_max_size;
+static Boolean recursive_inline;
+static Object *expanding_function;
+static Boolean cinline_funccallfound;
+
+void CInline_Init(void) {}
+static ENode *CInline_MakeNotNot(ENode *expr) {}
+static ENode *CInline_FoldConst(ENode *expr) {}
+SInt32 CInline_GetLocalID(Object *obj) {}
+static Boolean CInline_IsTrivialExpression(ENode *expr) {}
+Boolean CInline_ExpressionHasSideEffect(ENode *expr) {}
+static ENode *CInline_CopyExpressionSave(ENode *expr) {}
+static SInt32 CInline_TranslateID(SInt32 id) {}
+static SInt32 CInline_GetLabelStatementNumber(HashNameNode *name) {}
+static ENodeList *CInline_CopyNodeList(ENodeList *list) {}
+static EMemberInfo *CInline_CopyEMemberInfo(EMemberInfo *mi) {}
+static ENode *CInline_CopyNodes(ENode *node) {}
+static void CInline_CheckUsage(ENode *expr, Boolean flag) {}
+ENode *CInline_CopyExpression(ENode *expr, CInlineCopyMode mode) {}
+static UInt8 CInline_GetObjectSFlags(Object *obj) {}
+static void CInline_SetObjectSFlags(Object *obj, UInt8 sflags) {}
+static Object *CInline_NewLocalObject(Type *type, short qual, UInt8 sflags) {}
+static ENode *CInline_FuncArgConvert(ENode *expr) {}
+static ENode *CInline_RefArgTransform(ENode *expr, Boolean flag) {}
+static ENode *CInline_SetupArgsExpression(Object *obj, CI_FuncData *data, ENodeList *list) {}
+static void CInline_ReturnCheckCB(/* there should be args here */) {}
+static ENode *CInline_ReturnCheck(ENode *expr) {}
+static ENode *CInline_ReturnMemResult(void) {}
+static ENode *CInline_InlineFunctionExpression(ENode *expr) {}
+static Boolean CInline_CanExpand(ENode *expr) {}
+static SInt32 CInline_EstimateSizeOfExpr(ENode *expr, SInt32 a, SInt32 b) {}
+static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 a, SInt32 b) {}
+static SInt32 EstimateExpandedSizeOfExpr(ENode *expr, SInt32 b) {}
+static SInt32 EstimateExpandedSizeOfFunction(Statement *stmt) {}
+static Boolean CInline_InlineFunctionCheck(ENode *expr) {}
+static ENode *CInline_ExpandExpression(ENode *expr) {}
+static Statement *CInline_NewStatement(StatementType sttype) {}
+static ENode *CInline_LoadToTemp(ENode *expr, Object **obj) {}
+static ENode *CInline_SerializeEFORCELOAD(ENode *expr) {}
+static ENode *CInline_SerializeECOMMA(ENode *expr) {}
+static ENode *CInline_SerializeELOR(ENode *expr) {}
+static ENode *CInline_SerializeELAND(ENode *expr) {}
+static ENode *CInline_SerializeEPRECOMP(ENode *expr) {}
+static ENode *CInline_SerializeENULLCHECK(ENode *expr) {}
+static ENode *CInline_SerializeECOND(ENode *expr) {}
+static ENode *CInline_SerializeExpr(ENode *expr) {}
+void CInline_SerializeStatement(Statement *stmt) {}
+static void CInline_UnpackSwitch(Statement *stmt, CI_Statement *packed, CLabel **labels) {}
+Object *CInline_GetLocalObj(SInt32 id, Boolean flag) {}
+static ExceptionAction *CInline_UnpackActions(CI_Statement *packed, Boolean flag) {}
+static Statement *CInline_ExpandStatements(Object *obj, Statement *stmt, CI_FuncData *data, ENode *expr, CLabel *label, Object *obj2, Boolean flag) {}
+static Statement *CInline_InlineFunctionStatement(Statement *stmt, Boolean *success) {}
+static Statement *CInline_ExtractInlineFunction(Statement *stmt) {}
+static Statement *CInline_ExpandStatement(Statement *stmt) {}
+static void CInline_ForceReverseSearch(ENode *) {}
+static ENode *CInline_ForceReverseEvaluation(ENode *expr) {}
+static void CInline_ExportCheck(ENode *expr) {}
+static void CInline_Expand(Statement *stmt) {}
+SInt32 CInline_GetStatementNumber(Statement *first, Statement *stmt) {}
+static CI_Switch *CInline_PackSwitch(Statement *s1, Statement *s2) {}
+static Boolean CInline_CanInline(Object *obj, Statement *stmt) {}
+static ExceptionAction *CInline_PackActions(Statement *s1, Statement *s2) {}
+void CInline_PackIFunctionData(CI_FuncData *packed, Statement *stmt, Object *obj) {}
+void CInline_UnpackIFunctionData(Object *obj, CI_FuncData *packed, Statement *stmt) {}
+static void CInline_GenIFunctionCode(Object *obj, CI_FuncData *func, UInt8 unk) {}
+void CInline_AddDefaultFunctionAction(Object *obj) {}
+void CInline_AddInlineFunctionAction(Object *obj, TypeClass *tclass, FileOffsetInfo *fileoffset, TStream *stream, Boolean flag) {}
+void CInline_AddMemberFunctionAction(Object *obj, Type *a, Type *b, TemplateMember *tmemb) {}
+void CInline_AddTemplateFunctionAction(Object *obj, TemplateFunction *func, TemplFuncInstance *inst) {}
+static void CInline_AddFRefList_Object(Object *obj) {}
+static void CInline_AddFRefList_ExAction(ExceptionAction *exc) {}
+static void CInline_AddFRefList_ExprCB(ENode *expr) {}
+static void CInline_AddFRefList_Expr(ENode *expr) {}
+static void CInline_AddFRefList_Statement(Statement *stmt) {}
+static void CInline_AddFRefList_InlineFunc(CI_FuncData *data) {}
+static void CInline_GenerateTemplateInline(Object *obj) {}
+void CInline_ObjectAddrRef(Object *obj) {}
+static Boolean CInline_CheckDependencies(ObjectList *list) {}
+static Boolean CInline_IsSmallFunction(Object *obj, Statement *stmt) {}
+static Boolean CInline_NoFPLocals(void) {}
+void CInline_GenFunc(Statement *stmt, Object *obj, UInt8 unk) {}
+static void CInline_GenerateDefaultFunc(Object *obj) {}
+static TemplClassInst *CInline_FindNestedTemplInst(TemplClassInst *inst) {}
+static void CInline_GenerateInlineFunc(CI_Action *action) {}
+Boolean CInline_CanFreeLHeap(void) {}
+Boolean CInline_GenerateDeferredFuncs(void) {}
+static InitExpr *CInline_InitTemplateData(InitExpr *init) {}
+void CInline_Finish(void) {}
diff --git a/compiler_and_linker/unsorted/CMachine.c b/compiler_and_linker/unsorted/CMachine.c
index f34ec88..fd4aafc 100644
--- a/compiler_and_linker/unsorted/CMachine.c
+++ b/compiler_and_linker/unsorted/CMachine.c
@@ -186,6 +186,7 @@ SInt32 CMach_ArgumentAlignment(Type *type) {
return align;
}
+// TODO: investigate if this returns SInt16 actually
SInt32 CMach_AllocationAlignment(Type *type, UInt32 qual) {
SInt32 align;
SInt32 qualalign;
@@ -573,7 +574,7 @@ void CMach_InitIntMem(Type *type, CInt64 val, void *mem) {
}
}
-void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem) {
+void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem, Boolean flag) {
unsigned char uc[16];
unsigned short us[8];
unsigned int ul[4];
@@ -856,7 +857,7 @@ static SInt16 CMach_GetQualifiedStructAlign(TypeStruct *tstruct, Boolean flag) {
switch (copts.align_mode) {
case AlignMode3_1Byte:
- case AlignMode8:
+ case AlignMode8_Packed:
return 1;
case AlignMode0_Mac68k:
return 2;
@@ -941,7 +942,7 @@ static SInt16 CMach_GetQualifiedClassAlign(TypeClass *tclass, Boolean flag) {
switch (copts.align_mode) {
case AlignMode3_1Byte:
- case AlignMode8:
+ case AlignMode8_Packed:
return 1;
case AlignMode0_Mac68k:
return 2;
@@ -1047,7 +1048,7 @@ static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag) {
switch (copts.align_mode) {
case AlignMode3_1Byte:
- case AlignMode8:
+ case AlignMode8_Packed:
return 1;
case AlignMode4_2Byte:
case AlignMode5_4Byte:
@@ -1166,7 +1167,7 @@ static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 var, Boolean flag) {
align = 16;
switch (copts.align_mode) {
- case AlignMode8:
+ case AlignMode8_Packed:
align = 1;
break;
case AlignMode0_Mac68k:
@@ -1266,7 +1267,7 @@ SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual) {
switch (copts.align_mode) {
case AlignMode3_1Byte:
- case AlignMode8:
+ case AlignMode8_Packed:
required_alignment = 0;
break;
}
diff --git a/compiler_and_linker/unsorted/CMangler.c b/compiler_and_linker/unsorted/CMangler.c
new file mode 100644
index 0000000..569871e
--- /dev/null
+++ b/compiler_and_linker/unsorted/CMangler.c
@@ -0,0 +1,719 @@
+#include "compiler.h"
+#include "compiler/CError.h"
+#include "compiler/CInt64.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler/templates.h"
+#include "compiler/types.h"
+#include "cos.h"
+
+HashNameNode *constructor_name_node;
+HashNameNode *destructor_name_node;
+HashNameNode *asop_name_node;
+
+// forward decls
+static void CMangler_MangleClassName(TypeClass *tclass);
+static void CMangler_MangleTypeAppend(Type *type, UInt32 qual);
+static void CMangler_MangleArgs(FuncArg *args);
+
+void CMangler_Setup(void) {
+ constructor_name_node = GetHashNameNodeExport("__ct");
+ destructor_name_node = GetHashNameNodeExport("__dt");
+ asop_name_node = GetHashNameNodeExport("__as");
+}
+
+HashNameNode *CMangler_BasicDtorName(void) {
+ return GetHashNameNodeExport("__dtb");
+}
+
+HashNameNode *CMangler_VBaseDtorName(void) {
+ return GetHashNameNodeExport("__dtv");
+}
+
+HashNameNode *CMangler_ArrayDtorName(void) {
+ return GetHashNameNodeExport("__dta");
+}
+
+HashNameNode *CMangler_SDeleteDtorName(void) {
+ return GetHashNameNodeExport("__dts");
+}
+
+HashNameNode *CMangler_DeleteDtorName(void) {
+ return GetHashNameNodeExport("__dt");
+}
+
+char *CMangler_GetOperator(HashNameNode *opname) {
+ char *name;
+
+ if (opname == asop_name_node)
+ return "operator=";
+
+ name = opname->name;
+ if (!strcmp(name, "__nw")) return "operator new";
+ if (!strcmp(name, "__dl")) return "operator delete";
+ if (!strcmp(name, "__nwa")) return "operator new[]";
+ if (!strcmp(name, "__dla")) return "operator delete[]";
+ if (!strcmp(name, "__pl")) return "operator+";
+ if (!strcmp(name, "__mi")) return "operator-";
+ if (!strcmp(name, "__ml")) return "operator*";
+ if (!strcmp(name, "__dv")) return "operator/";
+ if (!strcmp(name, "__md")) return "operator%";
+ if (!strcmp(name, "__er")) return "operator^";
+ if (!strcmp(name, "__ad")) return "operator&";
+ if (!strcmp(name, "__or")) return "operator|";
+ if (!strcmp(name, "__co")) return "operator~";
+ if (!strcmp(name, "__nt")) return "operator!";
+ if (!strcmp(name, "__lt")) return "operator<";
+ if (!strcmp(name, "__gt")) return "operator>";
+ if (!strcmp(name, "__apl")) return "operator+=";
+ if (!strcmp(name, "__ami")) return "operator-=";
+ if (!strcmp(name, "__amu")) return "operator*=";
+ if (!strcmp(name, "__adv")) return "operator/=";
+ if (!strcmp(name, "__amd")) return "operator%=";
+ if (!strcmp(name, "__aer")) return "operator^=";
+ if (!strcmp(name, "__aad")) return "operator&=";
+ if (!strcmp(name, "__aor")) return "operator|=";
+ if (!strcmp(name, "__ls")) return "operator<<";
+ if (!strcmp(name, "__rs")) return "operator>>";
+ if (!strcmp(name, "__als")) return "operator<<=";
+ if (!strcmp(name, "__ars")) return "operator>>=";
+ if (!strcmp(name, "__eq")) return "operator==";
+ if (!strcmp(name, "__ne")) return "operator!=";
+ if (!strcmp(name, "__le")) return "operator<=";
+ if (!strcmp(name, "__ge")) return "operator>=";
+ if (!strcmp(name, "__aa")) return "operator&&";
+ if (!strcmp(name, "__oo")) return "operator||";
+ if (!strcmp(name, "__pp")) return "operator++";
+ if (!strcmp(name, "__mm")) return "operator--";
+ if (!strcmp(name, "__cm")) return "operator,";
+ if (!strcmp(name, "__rm")) return "operator->*";
+ if (!strcmp(name, "__rf")) return "operator*";
+ if (!strcmp(name, "__cl")) return "operator()";
+ if (!strcmp(name, "__vc")) return "operator[]";
+ return NULL;
+}
+
+HashNameNode *CMangler_OperatorName(short token) {
+ switch (token) {
+ case TK_NEW: return GetHashNameNodeExport("__nw");
+ case TK_DELETE: return GetHashNameNodeExport("__dl");
+ case TK_NEW_ARRAY: return GetHashNameNodeExport("__nwa");
+ case TK_DELETE_ARRAY: return GetHashNameNodeExport("__dla");
+ case '+': return GetHashNameNodeExport("__pl");
+ case '-': return GetHashNameNodeExport("__mi");
+ case '*': return GetHashNameNodeExport("__ml");
+ case '/': return GetHashNameNodeExport("__dv");
+ case '%': return GetHashNameNodeExport("__md");
+ case '^': return GetHashNameNodeExport("__er");
+ case '&': return GetHashNameNodeExport("__ad");
+ case '|': return GetHashNameNodeExport("__or");
+ case '~': return GetHashNameNodeExport("__co");
+ case '!': return GetHashNameNodeExport("__nt");
+ case '=': return asop_name_node;
+ case '<': return GetHashNameNodeExport("__lt");
+ case '>': return GetHashNameNodeExport("__gt");
+ case TK_ADD_ASSIGN: return GetHashNameNodeExport("__apl");
+ case TK_SUB_ASSIGN: return GetHashNameNodeExport("__ami");
+ case TK_MULT_ASSIGN: return GetHashNameNodeExport("__amu");
+ case TK_DIV_ASSIGN: return GetHashNameNodeExport("__adv");
+ case TK_MOD_ASSIGN: return GetHashNameNodeExport("__amd");
+ case TK_XOR_ASSIGN: return GetHashNameNodeExport("__aer");
+ case TK_AND_ASSIGN: return GetHashNameNodeExport("__aad");
+ case TK_OR_ASSIGN: return GetHashNameNodeExport("__aor");
+ case TK_SHL: return GetHashNameNodeExport("__ls");
+ case TK_SHR: return GetHashNameNodeExport("__rs");
+ case TK_SHL_ASSIGN: return GetHashNameNodeExport("__als");
+ case TK_SHR_ASSIGN: return GetHashNameNodeExport("__ars");
+ case TK_LOGICAL_EQ: return GetHashNameNodeExport("__eq");
+ case TK_LOGICAL_NE: return GetHashNameNodeExport("__ne");
+ case TK_LESS_EQUAL: return GetHashNameNodeExport("__le");
+ case TK_GREATER_EQUAL: return GetHashNameNodeExport("__ge");
+ case TK_LOGICAL_AND: return GetHashNameNodeExport("__aa");
+ case TK_LOGICAL_OR: return GetHashNameNodeExport("__oo");
+ case TK_INCREMENT: return GetHashNameNodeExport("__pp");
+ case TK_DECREMENT: return GetHashNameNodeExport("__mm");
+ case ',': return GetHashNameNodeExport("__cm");
+ case TK_ARROW_STAR: return GetHashNameNodeExport("__rm");
+ case TK_ARROW: return GetHashNameNodeExport("__rf");
+ case '(': return GetHashNameNodeExport("__cl");
+ case '[': return GetHashNameNodeExport("__vc");
+ default: return NULL;
+ }
+}
+
+HashNameNode *CMangler_VTableName(TypeClass *tclass) {
+ HashNameNode *name;
+
+ name_mangle_list.size = 0;
+ AppendGListName(&name_mangle_list, "__vt__");
+ CMangler_MangleClassName(tclass);
+ AppendGListByte(&name_mangle_list, 0);
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+HashNameNode *CMangler_RTTIObjectName(Type *type, UInt32 qual) {
+ HashNameNode *name;
+
+ name_mangle_list.size = 0;
+ AppendGListName(&name_mangle_list, "__RTTI__");
+ CMangler_MangleTypeAppend(type, qual);
+ AppendGListByte(&name_mangle_list, 0);
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+HashNameNode *CMangler_ThunkName(Object *obj, int a, int b, int c) {
+ HashNameNode *linkname;
+ HashNameNode *name;
+ char buf[64];
+
+ linkname = CMangler_GetLinkName(obj);
+ name_mangle_list.size = 0;
+ if (b == 0) {
+ if (c < 0)
+ sprintf(buf, "_@%ld@", -a);
+ else
+ sprintf(buf, "_@%ld@%ld@", -a, c);
+ } else {
+ sprintf(buf, "_@%ld@%ld@%ld@", -a, c, b);
+ }
+ AppendGListName(&name_mangle_list, buf);
+ AppendGListID(&name_mangle_list, linkname->name + 1);
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+static void CMangler_CheckTemplateArguments(TemplArg *arg) {
+ ENode *expr;
+
+ while (arg) {
+ if (arg->pid.type == TPT_NONTYPE) {
+ expr = arg->data.paramdecl.expr;
+#line 360
+ CError_ASSERT(expr);
+ if (expr->rtype->type != TYPETEMPLDEPEXPR) {
+ switch (expr->type) {
+ case EINTCONST:
+ break;
+ case EOBJREF:
+ CMangler_GetLinkName(expr->data.objref);
+ break;
+ default:
+#line 383
+ CError_FATAL();
+ }
+ }
+ }
+ arg = arg->next;
+ }
+}
+
+static void CMangler_AppendTemplateArgumentList(TemplArg *arg) {
+ ENode *expr;
+ char buf[32];
+
+ AppendGListByte(&name_mangle_list, '<');
+
+ while (arg) {
+ if (arg->pid.type == TPT_NONTYPE) {
+ expr = arg->data.paramdecl.expr;
+#line 409
+ CError_ASSERT(expr);
+ if (expr->rtype->type != TYPETEMPLDEPEXPR) {
+ switch (expr->type) {
+ case EINTCONST:
+ CInt64_PrintDec(buf, expr->data.intval);
+ AppendGListName(&name_mangle_list, buf);
+ break;
+ case EOBJREF:
+ AppendGListByte(&name_mangle_list, '&');
+ AppendGListName(&name_mangle_list, CMangler_GetLinkName(expr->data.objref)->name);
+ break;
+ default:
+#line 452
+ CError_FATAL();
+ }
+ } else {
+ AppendGListByte(&name_mangle_list, 'T');
+ }
+ } else if (arg->pid.type == TPT_TYPE) {
+ CMangler_MangleTypeAppend(arg->data.typeparam.type, arg->data.typeparam.qual);
+ } else {
+#line 467
+ CError_ASSERT(arg->pid.type == TPT_TEMPLATE);
+ CMangler_MangleTypeAppend(arg->data.ttargtype, 0);
+ }
+
+ if (arg->next)
+ AppendGListByte(&name_mangle_list, ',');
+ arg = arg->next;
+ }
+
+ AppendGListByte(&name_mangle_list, '>');
+}
+
+HashNameNode *CMangler_TemplateInstanceName(HashNameNode *basename, TemplArg *args) {
+ HashNameNode *name;
+
+ CMangler_CheckTemplateArguments(args);
+ name_mangle_list.size = 0;
+ AppendGListName(&name_mangle_list, basename->name);
+ CMangler_AppendTemplateArgumentList(args);
+ AppendGListByte(&name_mangle_list, 0);
+
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+static void CMangler_MangleTypeName(char *str) {
+ char buf[16];
+
+ sprintf(buf, "%d", strlen(str));
+ AppendGListName(&name_mangle_list, buf);
+ AppendGListName(&name_mangle_list, str);
+}
+
+static void CMangler_MangleNameSpaceName(NameSpace *nspace, char *str) {
+ char *stack[10];
+ int stackp;
+
+ stack[0] = str;
+ stackp = 1;
+ while (nspace) {
+ if (nspace->name) {
+ stack[stackp++] = nspace->name->name;
+ if (stackp >= 9)
+ break;
+ }
+ nspace = nspace->parent;
+ }
+
+ if (stackp > 1) {
+ AppendGListByte(&name_mangle_list, 'Q');
+ AppendGListByte(&name_mangle_list, '0' + stackp);
+ }
+
+ while (--stackp >= 0)
+ CMangler_MangleTypeName(stack[stackp]);
+}
+
+static void CMangler_MangleClassName(TypeClass *tclass) {
+ if (!tclass->classname)
+ CMangler_MangleNameSpaceName(tclass->nspace->parent, "class");
+ else
+ CMangler_MangleNameSpaceName(tclass->nspace->parent, tclass->nspace->name->name);
+}
+
+static void CMangler_MangleQualifier(UInt32 qual) {
+ if (qual & Q_CONST)
+ AppendGListByte(&name_mangle_list, 'C');
+ if (qual & Q_VOLATILE)
+ AppendGListByte(&name_mangle_list, 'V');
+}
+
+static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) {
+ char buf[16];
+
+ switch (type->type) {
+ case TYPEVOID:
+ CMangler_MangleQualifier(qual);
+ AppendGListByte(&name_mangle_list, 'v');
+ break;
+ case TYPEINT:
+ case TYPEFLOAT:
+ CMangler_MangleQualifier(qual);
+ switch (TYPE_INTEGRAL(type)->integral) {
+ case IT_BOOL:
+ AppendGListByte(&name_mangle_list, 'b');
+ return;
+ case IT_CHAR:
+ AppendGListByte(&name_mangle_list, 'c');
+ return;
+ case IT_WCHAR_T:
+ AppendGListByte(&name_mangle_list, 'w');
+ return;
+ case IT_UCHAR:
+ AppendGListName(&name_mangle_list, "Uc");
+ return;
+ case IT_SCHAR:
+ AppendGListName(&name_mangle_list, "Sc");
+ return;
+ case IT_SHORT:
+ AppendGListByte(&name_mangle_list, 's');
+ return;
+ case IT_USHORT:
+ AppendGListName(&name_mangle_list, "Us");
+ return;
+ case IT_INT:
+ AppendGListByte(&name_mangle_list, 'i');
+ return;
+ case IT_UINT:
+ AppendGListName(&name_mangle_list, "Ui");
+ return;
+ case IT_LONG:
+ AppendGListByte(&name_mangle_list, 'l');
+ return;
+ case IT_ULONG:
+ AppendGListName(&name_mangle_list, "Ul");
+ return;
+ case IT_LONGLONG:
+ AppendGListByte(&name_mangle_list, 'x');
+ return;
+ case IT_ULONGLONG:
+ AppendGListName(&name_mangle_list, "Ux");
+ return;
+ case IT_FLOAT:
+ AppendGListByte(&name_mangle_list, 'f');
+ return;
+ case IT_SHORTDOUBLE:
+ AppendGListByte(&name_mangle_list, 'D');
+ return;
+ case IT_DOUBLE:
+ AppendGListByte(&name_mangle_list, 'd');
+ return;
+ case IT_LONGDOUBLE:
+ AppendGListByte(&name_mangle_list, 'r');
+ return;
+ default:
+#line 619
+ CError_FATAL();
+ }
+ case TYPEENUM:
+ CMangler_MangleQualifier(qual);
+ if (!TYPE_ENUM(type)->enumname)
+ CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, "enum");
+ else
+ CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname->name);
+ break;
+ case TYPEPOINTER:
+ CMangler_MangleQualifier(TYPE_POINTER(type)->qual);
+ if (TYPE_POINTER(type)->qual & Q_REFERENCE)
+ AppendGListByte(&name_mangle_list, 'R');
+ else
+ AppendGListByte(&name_mangle_list, 'P');
+ CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual);
+ break;
+ case TYPEMEMBERPOINTER:
+ if (TYPE_MEMBER_POINTER(type)->ty2->type != TYPECLASS) {
+ AppendGListName(&name_mangle_list, "3<T>");
+ } else {
+ CMangler_MangleQualifier(TYPE_MEMBER_POINTER(type)->qual);
+ AppendGListByte(&name_mangle_list, 'M');
+ CMangler_MangleClassName(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2));
+ CMangler_MangleTypeAppend(TYPE_MEMBER_POINTER(type)->ty1, qual);
+ }
+ break;
+ case TYPEARRAY:
+ AppendGListByte(&name_mangle_list, 'A');
+ if (TYPE_POINTER(type)->target->size) {
+ sprintf(buf, "%ld", type->size / TYPE_POINTER(type)->target->size);
+ AppendGListName(&name_mangle_list, buf);
+ } else {
+ AppendGListByte(&name_mangle_list, '0');
+ }
+ AppendGListByte(&name_mangle_list, '_');
+ CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual);
+ break;
+ case TYPEFUNC:
+ CMangler_MangleQualifier(qual);
+ AppendGListByte(&name_mangle_list, 'F');
+ CMangler_MangleArgs(TYPE_FUNC(type)->args);
+ AppendGListByte(&name_mangle_list, '_');
+ CMangler_MangleTypeAppend(TYPE_FUNC(type)->functype, TYPE_FUNC(type)->qual);
+ break;
+ case TYPESTRUCT:
+ CMangler_MangleQualifier(qual);
+ switch (TYPE_STRUCT(type)->stype) {
+ case STRUCT_TYPE_4:
+ AppendGListName(&name_mangle_list, "XUc");
+ return;
+ case STRUCT_TYPE_5:
+ AppendGListName(&name_mangle_list, "Xc");
+ return;
+ case STRUCT_TYPE_6:
+ AppendGListName(&name_mangle_list, "XC");
+ return;
+ case STRUCT_TYPE_7:
+ AppendGListName(&name_mangle_list, "XUs");
+ return;
+ case STRUCT_TYPE_8:
+ AppendGListName(&name_mangle_list, "Xs");
+ return;
+ case STRUCT_TYPE_9:
+ AppendGListName(&name_mangle_list, "XS");
+ return;
+ case STRUCT_TYPE_A:
+ AppendGListName(&name_mangle_list, "XUi");
+ return;
+ case STRUCT_TYPE_B:
+ AppendGListName(&name_mangle_list, "Xi");
+ return;
+ case STRUCT_TYPE_C:
+ AppendGListName(&name_mangle_list, "XI");
+ return;
+ case STRUCT_TYPE_D:
+ AppendGListName(&name_mangle_list, "Xf");
+ return;
+ case STRUCT_TYPE_E:
+ AppendGListName(&name_mangle_list, "Xp");
+ return;
+ }
+
+ if (TYPE_STRUCT(type)->name && !IsTempName(TYPE_STRUCT(type)->name)) {
+ CMangler_MangleTypeName(TYPE_STRUCT(type)->name->name);
+ return;
+ }
+
+ switch (TYPE_STRUCT(type)->stype) {
+ case STRUCT_TYPE_STRUCT:
+ AppendGListName(&name_mangle_list, "struct");
+ break;
+ case STRUCT_TYPE_UNION:
+ AppendGListName(&name_mangle_list, "union");
+ break;
+ case STRUCT_TYPE_CLASS:
+ AppendGListName(&name_mangle_list, "class");
+ break;
+ default:
+#line 701
+ CError_FATAL();
+ }
+ break;
+
+ case TYPECLASS:
+ CMangler_MangleQualifier(qual);
+ CMangler_MangleClassName(TYPE_CLASS(type));
+ break;
+
+ case TYPETEMPLATE:
+ AppendGListName(&name_mangle_list, "1T");
+ break;
+
+ default:
+#line 716
+ CError_FATAL();
+ }
+}
+
+void CMangler_MangleType(Type *type, UInt32 qual) {
+ name_mangle_list.size = 0;
+ CMangler_MangleTypeAppend(type, qual);
+}
+
+static void CMangler_MangleArgs(FuncArg *args) {
+ TypePointer ptr;
+
+ if (args) {
+ if (args->type) {
+ while (args) {
+ if (args != &elipsis && args != &oldstyle) {
+ if (args->type->type == TYPEPOINTER) {
+ ptr = *TYPE_POINTER(args->type);
+ ptr.qual &= ~(Q_CONST | Q_VOLATILE);
+ CMangler_MangleTypeAppend((Type *) &ptr, args->qual);
+ } else {
+ CMangler_MangleTypeAppend(args->type, 0);
+ }
+ } else {
+ AppendGListByte(&name_mangle_list, 'e');
+ }
+ args = args->next;
+ }
+ } else {
+ AppendGListByte(&name_mangle_list, 'e');
+ }
+ } else {
+ AppendGListByte(&name_mangle_list, 'v');
+ }
+}
+
+static void CMangler_MangleFunction(Object *obj, NameSpace *nspace) {
+ TypeFunc *tfunc = TYPE_FUNC(obj->type);
+ FuncArg *arg = tfunc->args;
+
+ AppendGListName(&name_mangle_list, obj->name->name);
+ if (obj->u.func.inst) {
+ if (tfunc->flags & FUNC_FLAGS_40)
+ CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual);
+ CMangler_AppendTemplateArgumentList(obj->u.func.inst->args);
+ }
+ AppendGListName(&name_mangle_list, "__");
+ while (nspace && nspace->name == NULL)
+ nspace = nspace->parent;
+
+ if (nspace) {
+ CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name);
+ if (nspace->theclass) {
+ if (obj->name == destructor_name_node) {
+ AppendGListName(&name_mangle_list, "Fv");
+ return;
+ }
+ if (arg) {
+ if (obj->name == constructor_name_node) {
+ arg = arg->next;
+ if (arg && (nspace->theclass->flags & CLASS_FLAGS_20))
+ arg = arg->next;
+ } else {
+ if ((tfunc->flags & FUNC_FLAGS_METHOD) && !TYPE_METHOD(tfunc)->x26) {
+ CMangler_MangleQualifier(arg->qual);
+ arg = arg->next;
+ }
+ }
+ }
+ }
+ }
+
+ AppendGListByte(&name_mangle_list, 'F');
+ CMangler_MangleArgs(arg);
+ if (obj->u.func.inst && copts.new_mangler) {
+ AppendGListByte(&name_mangle_list, '_');
+ CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual);
+ }
+}
+
+HashNameNode *CMangler_ConversionFuncName(Type *type, UInt32 qual) {
+ HashNameNode *name;
+
+ if (CTemplTool_IsTemplateArgumentDependentType(type))
+ return GetHashNameNodeExport("__op");
+
+ name_mangle_list.size = 0;
+ AppendGListName(&name_mangle_list, "__op");
+ CMangler_MangleTypeAppend(type, qual);
+ AppendGListByte(&name_mangle_list, 0);
+
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+static HashNameNode *CMangler_MangleNameToUpper(char *str) {
+ HashNameNode *name;
+
+ name_mangle_list.size = 0;
+ while (*str) {
+ AppendGListByte(&name_mangle_list, toupper(*(str++)));
+ }
+ AppendGListByte(&name_mangle_list, 0);
+
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+static HashNameNode *CMangler_FunctionLinkName(Object *obj) {
+ HashNameNode *name;
+ NameSpace *nspace;
+
+ if (obj->u.func.inst)
+ CMangler_CheckTemplateArguments(obj->u.func.inst->args);
+
+ for (nspace = obj->nspace; nspace; nspace = nspace->parent) {
+ if (nspace->name)
+ break;
+ }
+
+ name_mangle_list.size = 0;
+ if (is_pascal_object(obj) && (!nspace || !nspace->theclass)) {
+ AppendGListData(&name_mangle_list, "_", 1);
+ AppendGListID(&name_mangle_list, obj->name->name);
+ } else if ((obj->qual & Q_80000) && (strcmp("main", obj->name->name) || (obj->nspace != cscope_root))) {
+ AppendGListData(&name_mangle_list, "_", 1);
+ CMangler_MangleFunction(obj, nspace);
+ AppendGListByte(&name_mangle_list, 0);
+ } else {
+ AppendGListData(&name_mangle_list, "_", 1);
+ AppendGListID(&name_mangle_list, obj->name->name);
+ }
+
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+HashNameNode *CMangler_GetCovariantFunctionName(Object *obj, Type *type) {
+ HashNameNode *linkname;
+ HashNameNode *name;
+
+ linkname = CMangler_GetLinkName(obj);
+ name_mangle_list.size = 0;
+ AppendGListName(&name_mangle_list, linkname->name);
+ AppendGListName(&name_mangle_list, "@@");
+ CMangler_MangleTypeAppend(type, 0);
+ AppendGListByte(&name_mangle_list, 0);
+
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+static HashNameNode *CMangler_DataLinkName(Object *obj) {
+ NameSpace *nspace;
+ HashNameNode *name;
+
+ nspace = obj->nspace;
+ while (nspace && nspace->name == NULL)
+ nspace = nspace->parent;
+
+ name_mangle_list.size = 0;
+ AppendGListData(&name_mangle_list, "_", 1);
+ AppendGListName(&name_mangle_list, obj->name->name);
+
+ while (nspace && nspace->name == NULL)
+ nspace = nspace->parent;
+ if (nspace && (obj->qual & Q_80000)) {
+ AppendGListName(&name_mangle_list, "__");
+ CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name);
+ }
+ AppendGListByte(&name_mangle_list, 0);
+
+ COS_LockHandle(name_mangle_list.data);
+ name = GetHashNameNodeExport(*name_mangle_list.data);
+ COS_UnlockHandle(name_mangle_list.data);
+ return name;
+}
+
+HashNameNode *CMangler_GetLinkName(Object *obj) {
+ while (obj->datatype == DALIAS)
+ obj = obj->u.alias.object;
+
+ switch (obj->datatype) {
+ case DFUNC:
+ case DVFUNC:
+ if (!obj->u.func.linkname)
+ obj->u.func.linkname = CMangler_FunctionLinkName(obj);
+ return obj->u.func.linkname;
+ case DDATA:
+ if (!obj->u.data.linkname)
+ obj->u.data.linkname = CMangler_DataLinkName(obj);
+ return obj->u.data.linkname;
+ case DINLINEFUNC:
+ return CMangler_FunctionLinkName(obj);
+ case DLOCAL:
+ case DABSOLUTE:
+ case DLABEL:
+ return obj->name;
+ case DNONLAZYPTR:
+ if (!obj->u.toc.linkname)
+ obj->u.toc.linkname = CMangler_DataLinkName(obj);
+ return obj->u.toc.linkname;
+ default:
+#line 1110
+ CError_FATAL();
+ return NULL;
+ }
+}
diff --git a/compiler_and_linker/unsorted/CParser.c b/compiler_and_linker/unsorted/CParser.c
new file mode 100644
index 0000000..8228159
--- /dev/null
+++ b/compiler_and_linker/unsorted/CParser.c
@@ -0,0 +1,3520 @@
+#include "compiler/CParser.h"
+#include "compiler/CABI.h"
+#include "compiler/CClass.h"
+#include "compiler/CDecl.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInit.h"
+#include "compiler/CInline.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CMangler.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/CScope.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler/templates.h"
+#include "cos.h"
+
+// TODO MOVE ME
+extern SInt32 symdecloffset;
+extern void CSOM_Setup(Boolean is_precompiler);
+extern void CSOM_Cleanup(void);
+extern void CIRTrans_Setup(void);
+extern void CObjC_Setup(void);
+extern void CObjC_GenerateModule(void);
+extern Type *CObjC_ParseTypeProtocol(Type *type);
+extern void CObjC_ParseProtocol(void);
+extern void CObjC_ParseClassDeclaration(void);
+extern void CObjC_ParseInterface(void);
+extern void CObjC_ParseImplementation(void);
+extern void CTempl_Setup(void);
+extern void CTempl_Parse(TypeClass *tclass, short access);
+extern Boolean CTempl_Instantiate(void);
+extern Boolean CInline_GenerateDeferredFuncs(void);
+extern void CTempl_Cleanup();
+extern void CIRTrans_Cleanup();
+extern void CObjC_Cleanup();
+extern void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *declinfo);
+extern void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *declinfo);
+extern void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *declinfo);
+extern Boolean CTemplTool_TemplDepTypeCompare(TypeTemplDep *a, TypeTemplDep *b);
+extern Boolean CTemplTool_IsSameTemplateType(Type *a, Type *b);
+extern TemplStack *ctempl_curinstance;
+extern Type *CObjC_ParseID(void);
+extern void CodeGen_UpdateOptimizerOptions(void);
+
+FileOffsetInfo cparser_fileoffset;
+TStreamElement symdecltoken;
+ParserTryBlock *trychain;
+Boolean inassembler;
+Boolean dont_set_references;
+TypeStruct ptmstruct;
+TypeStruct catchinfostruct;
+Boolean in_assembler;
+Boolean illegalimplicitconversion;
+Boolean in_func_arglist;
+NameSpaceName *newp_fobj;
+NameSpaceName *newa_fobj;
+NameSpaceName *delp_fobj;
+NameSpaceName *dela_fobj;
+Object *newh_func;
+Object *delh_func;
+Object *copy_func;
+Object *clear_func;
+Object *Rgtid_func;
+Object *Rdync_func;
+Object *rt_ptmf_cast;
+Object *rt_ptmf_cmpr;
+Object *rt_ptmf_test;
+Object *rt_ptmf_call;
+Object *rt_ptmf_scall;
+Object *rt_ptmf_call4;
+Object *rt_ptmf_scall4;
+Object *rt_ptmf_null;
+Object *rt_som_new;
+Object *rt_som_newcheck;
+Object *rt_som_check;
+Object *rt_som_glue1;
+Object *rt_som_glue2;
+Object *rt_som_glue3;
+Object *carr_func;
+Object *cnar_func;
+Object *darr_func;
+Object *dnar_func;
+Object *dnar3_func;
+Object *Xgreg_func;
+Object *Xthrw_func;
+Object *Xicth_func;
+Object *Xecth_func;
+Object *Xunex_func;
+COpts copts;
+GList name_mangle_list;
+HashNameNode *no_name_node;
+HashNameNode *temp_argument_name;
+HashNameNode *this_name_node;
+HashNameNode *self_name_node;
+HashNameNode *vptr_name_node;
+CallbackAction *callbackactions;
+Boolean fatalerrors;
+Boolean anyerrors;
+jmp_buf errorreturn;
+static HashNameNode *uniquenamespacename;
+static SInt32 uniqueid;
+
+struct ClassAction {
+ struct ClassAction *next;
+ TypeClass *tclass;
+};
+static struct ClassAction *cparser_classactions;
+
+struct ParentCleanup {
+ struct ParentCleanup *next;
+ TypeClass *tclass;
+};
+static struct ParentCleanup *cparser_parentcleanup;
+
+struct SFuncList {
+ struct SFuncList *next;
+ Object *func;
+ Object *obj;
+ ENode *expr;
+};
+static struct SFuncList *cparser_sfunclist;
+
+char string[256];
+SInt32 compilererrornum;
+SInt32 compilererrfile;
+SInt32 compilererrline;
+
+Type sttemplexpr = {TYPETEMPLDEPEXPR, 0};
+Type stillegal = {TYPEILLEGAL, 1};
+Type stvoid = {TYPEVOID, 0};
+TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0};
+TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0};
+
+// forward declarations
+static void CParser_ParseDeclaration(DeclInfo *di);
+
+Object *CParser_NewRTFunc(Type *rettype, HashNameNode *name, Boolean flag, int argcount, ...) {
+ Object *obj;
+ FuncArg *args;
+ FuncArg *arg;
+ TypeFunc *tfunc;
+ va_list va;
+
+ args = NULL;
+ if (argcount) {
+ va_start(va, argcount);
+ while (--argcount >= 0) {
+ if (args) {
+ arg->next = CParser_NewFuncArg();
+ arg = arg->next;
+ } else {
+ arg = CParser_NewFuncArg();
+ args = arg;
+ }
+ arg->type = va_arg(va, Type *);
+ }
+ va_end(va);
+ }
+
+ obj = CParser_NewFunctionObject(NULL);
+
+ tfunc = galloc(sizeof(TypeFunc));
+ memclrw(tfunc, sizeof(TypeFunc));
+ tfunc->type = TYPEFUNC;
+ tfunc->functype = rettype;
+ tfunc->args = args;
+ CDecl_SetFuncFlags(tfunc, 0);
+
+ obj->name = name;
+ obj->type = TYPE(tfunc);
+ if (flag == 1)
+ obj->qual = Q_80000;
+
+ return obj;
+}
+
+Boolean CParser_IsPublicRuntimeObject(Object *obj) {
+ if (newp_fobj->first.object == OBJ_BASE(obj) && !newp_fobj->first.next)
+ return 1;
+ if (newa_fobj->first.object == OBJ_BASE(obj) && !newa_fobj->first.next)
+ return 1;
+ if (delp_fobj->first.object == OBJ_BASE(obj) && !delp_fobj->first.next)
+ return 1;
+ if (dela_fobj->first.object == OBJ_BASE(obj) && !dela_fobj->first.next)
+ return 1;
+ return CodeGen_IsPublicRuntimeObject(obj);
+}
+
+Object *CParser_FindPublicRuntimeObject(HashNameNode *name) {
+ NameSpaceObjectList *list = CScope_FindName(cscope_root, name);
+ if (list && list->object->otype == OT_OBJECT && (!list->next || list->next->object->otype == OT_TYPETAG))
+ return OBJECT(list->object);
+ else
+ return NULL;
+}
+
+Boolean CParser_ReInitRuntimeObjects(Boolean is_precompiler) {
+ if (!(newp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW))))
+ return 0;
+ if (!(newa_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW_ARRAY))))
+ return 0;
+ if (!(delp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE))))
+ return 0;
+ if (!(dela_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE_ARRAY))))
+ return 0;
+
+ newh_func->name = GetHashNameNodeExport("__new_hdl");
+ delh_func->name = GetHashNameNodeExport("__del_hdl");
+ copy_func->name = GetHashNameNodeExport("__copy");
+ clear_func->name = GetHashNameNodeExport("__clear");
+ Rgtid_func->name = GetHashNameNodeExport("__get_typeid");
+ Rdync_func->name = GetHashNameNodeExport("__dynamic_cast");
+ rt_ptmf_cast->name = GetHashNameNodeExport("__ptmf_cast");
+ rt_ptmf_cmpr->name = GetHashNameNodeExport("__ptmf_cmpr");
+ rt_ptmf_test->name = GetHashNameNodeExport("__ptmf_test");
+ rt_ptmf_call->name = GetHashNameNodeExport("__ptmf_call");
+ rt_ptmf_scall->name = GetHashNameNodeExport("__ptmf_scall");
+ rt_ptmf_call4->name = GetHashNameNodeExport("__ptmf_call4");
+ rt_ptmf_scall4->name = GetHashNameNodeExport("__ptmf_scall4");
+ rt_ptmf_null->name = GetHashNameNodeExport("__ptmf_null");
+ rt_som_new->name = GetHashNameNodeExport("__som_new");
+ rt_som_newcheck->name = GetHashNameNodeExport("__som_check_new");
+ rt_som_check->name = GetHashNameNodeExport("__som_check_ev");
+ rt_som_glue1->name = GetHashNameNodeExport("_som_ptrgl4");
+ rt_som_glue2->name = GetHashNameNodeExport("_som_ptrgl5");
+ rt_som_glue3->name = GetHashNameNodeExport("_som_ptrgl_");
+ carr_func->name = GetHashNameNodeExport("__construct_array");
+ cnar_func->name = GetHashNameNodeExport("__construct_new_array");
+ darr_func->name = GetHashNameNodeExport("__destroy_arr");
+ dnar_func->name = GetHashNameNodeExport("__destroy_new_array");
+ dnar3_func->name = GetHashNameNodeExport("__destroy_new_array3");
+ Xgreg_func->name = GetHashNameNodeExport("__register_global_object");
+ Xthrw_func->name = GetHashNameNodeExport("__throw");
+ Xicth_func->name = GetHashNameNodeExport("__init__catch");
+ Xecth_func->name = GetHashNameNodeExport("__end__catch");
+ Xunex_func->name = GetHashNameNodeExport("__unexpected");
+
+ CMangler_Setup();
+
+ no_name_node = GetHashNameNodeExport("@no_name@");
+ temp_argument_name = GetHashNameNodeExport("@temp_ptr@");
+ this_name_node = GetHashNameNodeExport("this");
+ self_name_node = GetHashNameNodeExport("self");
+ vptr_name_node = GetHashNameNodeExport("__vptr$");
+
+ CSOM_Setup(is_precompiler);
+ return CodeGen_ReInitRuntimeObjects(is_precompiler);
+}
+
+static void CParser_SetupRuntimeObjects(void) {
+ ExceptSpecList *exspecs;
+ Type *sizet;
+ Object *func;
+
+ exspecs = galloc(sizeof(ExceptSpecList));
+ memclrw(exspecs, sizeof(ExceptSpecList));
+
+ sizet = CABI_GetSizeTType();
+
+ func = CParser_NewRTFunc(
+ TYPE(&void_ptr), CMangler_OperatorName(TK_NEW), 1,
+ 1, sizet);
+ CScope_AddGlobalObject(func);
+
+ func = CParser_NewRTFunc(
+ TYPE(&void_ptr), CMangler_OperatorName(TK_NEW_ARRAY), 1,
+ 1, sizet);
+ CScope_AddGlobalObject(func);
+
+ func = CParser_NewRTFunc(
+ TYPE(&stvoid), CMangler_OperatorName(TK_DELETE), 1,
+ 1, &void_ptr);
+#line 379
+ CError_ASSERT(IS_TYPE_FUNC(func->type));
+ TYPE_FUNC(func->type)->exspecs = exspecs;
+ CScope_AddGlobalObject(func);
+
+ func = CParser_NewRTFunc(
+ TYPE(&stvoid), CMangler_OperatorName(TK_DELETE_ARRAY), 1,
+ 1, &void_ptr);
+#line 387
+ CError_ASSERT(IS_TYPE_FUNC(func->type));
+ TYPE_FUNC(func->type)->exspecs = exspecs;
+ CScope_AddGlobalObject(func);
+
+ newh_func = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 0,
+ 1, sizet);
+ delh_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 1, &void_ptr);
+
+ Rgtid_func = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 0,
+ 2, &void_ptr, &stsignedlong);
+ Rdync_func = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 0,
+ 5, &void_ptr, &stsignedlong, &void_ptr, &void_ptr, &stsignedshort);
+
+ copy_func = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 2,
+ 3, &void_ptr, &void_ptr, sizet);
+ clear_func = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 2,
+ 2, &void_ptr, sizet);
+
+ rt_ptmf_cast = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 2,
+ 3, &stsignedlong, &void_ptr, &void_ptr);
+ rt_ptmf_cmpr = CParser_NewRTFunc(
+ TYPE(&stsignedlong), NULL, 2,
+ 2, &void_ptr, &void_ptr);
+ rt_ptmf_test = CParser_NewRTFunc(
+ TYPE(&stsignedlong), NULL, 2,
+ 1, &void_ptr);
+
+ rt_ptmf_call = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
+ rt_ptmf_scall = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
+ rt_ptmf_call4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
+ rt_ptmf_scall4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
+
+ rt_ptmf_null = CParser_NewGlobalDataObject(NULL);
+ rt_ptmf_null->type = &stvoid;
+
+ rt_som_new = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 2,
+ 3, &void_ptr, &stsignedlong, &stsignedlong);
+ rt_som_newcheck = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 1, &void_ptr);
+ rt_som_check = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 1, &void_ptr);
+ rt_som_glue1 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
+ rt_som_glue2 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
+ rt_som_glue3 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
+
+ carr_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet);
+ cnar_func = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 0,
+ 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet);
+ darr_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 4, &void_ptr, &void_ptr, sizet, sizet);
+ dnar_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 2, &void_ptr, &void_ptr);
+ dnar3_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 4, &void_ptr, &void_ptr, &void_ptr, &stsignedshort);
+
+ Xgreg_func = CParser_NewRTFunc(
+ TYPE(&void_ptr), NULL, 0,
+ 3, &void_ptr, &void_ptr, &void_ptr);
+ Xthrw_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 3, &void_ptr, &void_ptr, &void_ptr);
+ Xicth_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 1, &void_ptr);
+ Xecth_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 1, &void_ptr);
+ Xunex_func = CParser_NewRTFunc(
+ TYPE(&stvoid), NULL, 0,
+ 1, &void_ptr);
+
+ CodeGen_SetupRuntimeObjects();
+#line 534
+ CError_ASSERT(CParser_ReInitRuntimeObjects(0));
+}
+
+void CParser_Setup(void) {
+ CScope_Setup();
+
+ name_mangle_list.data = NULL;
+ if (InitGList(&name_mangle_list, 256))
+ CError_NoMem();
+
+ void_ptr.size = 4;
+ CError_Init();
+ CInit_Init();
+ CClass_Init();
+ CIRTrans_Setup();
+ CObjC_Setup();
+ CInline_Init();
+
+ in_assembler = 0;
+ in_func_arglist = 0;
+ CParser_SetUniqueID(1);
+ dont_set_references = 0;
+
+ copts.side_effects = 1;
+ cparser_classactions = NULL;
+ name_obj_check = NULL;
+ callbackactions = NULL;
+ init_expressions = NULL;
+ cparser_sfunclist = NULL;
+ trychain = NULL;
+ cparser_parentcleanup = NULL;
+
+ memclrw(&cparser_fileoffset, sizeof(FileOffsetInfo));
+
+ memclrw(&catchinfostruct, sizeof(TypeStruct));
+ catchinfostruct.type = TYPESTRUCT;
+ catchinfostruct.size = 24;
+ catchinfostruct.stype = STRUCT_TYPE_STRUCT;
+ catchinfostruct.align = 4;
+
+ memclrw(&ptmstruct, sizeof(TypeStruct));
+ ptmstruct.type = TYPESTRUCT;
+ ptmstruct.size = 12;
+ ptmstruct.stype = STRUCT_TYPE_STRUCT;
+ ptmstruct.align = 4;
+
+ CMach_Configure();
+ CTempl_Setup();
+
+ uniquenamespacename = NULL;
+ disallowgreaterthan = 0;
+
+ CParser_SetupRuntimeObjects();
+}
+
+void CParser_Cleanup(void) {
+ CTempl_Cleanup();
+ CIRTrans_Cleanup();
+ CObjC_Cleanup();
+ CScope_Cleanup();
+ FreeGList(&name_mangle_list);
+}
+
+short GetPrec(short token) {
+ switch (token) {
+ case '%':
+ case '*':
+ case '/':
+ return 11;
+ case '+':
+ case '-':
+ return 10;
+ case TK_SHL:
+ case TK_SHR:
+ return 9;
+ case '<':
+ case '>':
+ case TK_LESS_EQUAL:
+ case TK_GREATER_EQUAL:
+ return 8;
+ case TK_LOGICAL_EQ:
+ case TK_LOGICAL_NE:
+ return 7;
+ case '&':
+ return 6;
+ case '^':
+ return 5;
+ case '|':
+ return 4;
+ case TK_LOGICAL_AND:
+ return 3;
+ case TK_LOGICAL_OR:
+ return 2;
+ default:
+ return 0;
+ }
+}
+
+Boolean CParser_ParseOperatorName(short *token, Boolean flag1, Boolean flag2) {
+ HashNameNode *name;
+
+ switch ((tk = lex())) {
+ case TK_NEW:
+ case TK_DELETE:
+ if (lookahead() == '[') {
+ lex();
+ if (lex() != ']')
+ CError_Error(125);
+ //if (tk == TK_NEW)
+ // tk = TK_NEW_ARRAY;
+ //else
+ // tk = TK_DELETE_ARRAY;
+ tk = (tk == TK_NEW) ? TK_NEW_ARRAY : TK_DELETE_ARRAY;
+ }
+ break;
+ case '(':
+ if ((tk = lex()) != ')') {
+ CError_Error(204);
+ return 0;
+ }
+ tk = '(';
+ break;
+ case '[':
+ if ((tk = lex()) != ']') {
+ CError_Error(204);
+ return 0;
+ }
+ tk = '[';
+ break;
+ }
+
+ if ((name = CMangler_OperatorName(tk))) {
+ if (token)
+ *token = tk;
+ tk = lex();
+ tkidentifier = name;
+ return 1;
+ }
+
+ if (flag1) {
+ if (flag2) {
+ DeclInfo declinfo;
+ memclrw(&declinfo, sizeof(DeclInfo));
+ conversion_type_name(&declinfo);
+ tkidentifier = CMangler_ConversionFuncName(declinfo.thetype, declinfo.qual);
+ }
+ if (token)
+ *token = 0;
+ return 1;
+ } else {
+ CError_Error(204);
+ return 0;
+ }
+}
+
+SInt32 CParser_GetUniqueID(void) {
+ return uniqueid++;
+}
+
+void CParser_PrintUniqueID(char *buf) {
+ SInt32 id;
+ char mybuf[16];
+ char *ptr;
+
+ ptr = mybuf;
+ id = CParser_GetUniqueID();
+ while (id) {
+ *ptr = '0' + (id - ((id / 10) * 10));
+ id = id / 10;
+ ptr++;
+ }
+
+ while (ptr > mybuf)
+ *(buf++) = *(--ptr);
+
+ *buf = 0;
+}
+
+void CParser_SetUniqueID(SInt32 id) {
+ uniqueid = id;
+}
+
+HashNameNode *CParser_GetUniqueName(void) {
+ char buf[20];
+ buf[0] = '@';
+ CParser_PrintUniqueID(buf + 1);
+ return GetHashNameNodeExport(buf);
+}
+
+HashNameNode *CParser_NameConcat(char *a, char *b) {
+ char mybuf[256];
+ char *buf;
+ char *dst;
+ int len;
+
+ len = strlen(a) + strlen(b);
+ if (len > (sizeof(mybuf) - 1)) {
+ buf = lalloc(len + 1);
+ dst = buf;
+ } else {
+ buf = mybuf;
+ dst = buf;
+ }
+
+ while (*a)
+ *(dst++) = *(a++);
+ while (*b)
+ *(dst++) = *(b++);
+ *dst = 0;
+
+ return GetHashNameNodeExport(buf);
+}
+
+HashNameNode *CParser_AppendUniqueName(char *prefix) {
+ char buf[256];
+ char *dst;
+ int i;
+
+ dst = buf;
+ for (i = 0; *prefix && i < 240; i++) {
+ *(dst++) = *(prefix++);
+ }
+ *(dst++) = '$';
+
+ CParser_PrintUniqueID(dst);
+ return GetHashNameNodeExport(buf);
+}
+
+HashNameNode *CParser_AppendUniqueNameFile(char *prefix) {
+ Str255 filename;
+ char buf[256];
+ char *src;
+ char *dst;
+ char c;
+ int i;
+ int j;
+ int len;
+
+ dst = buf;
+ for (i = 0; *prefix && i < 200; i++) {
+ *(dst++) = *(prefix++);
+ }
+ *(dst++) = '$';
+
+ CParser_PrintUniqueID(dst);
+
+ while (*dst) {
+ dst++;
+ i++;
+ }
+
+ COS_FileGetFSSpecInfo(&cparamblkptr->mainFileSpec, NULL, NULL, filename);
+ src = (char *) &filename[1];
+ len = filename[0];
+ for (j = 0; j < len && i < 255; j++, i++) {
+ c = *(src++);
+ if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9'))
+ c = '_';
+ *(dst++) = c;
+ }
+
+ dst[0] = 0;
+ return GetHashNameNodeExport(buf);
+}
+
+static HashNameNode *CParser_GetUnnamedNameSpaceName(void) {
+ Str255 filename;
+ char buf[256];
+ char *src;
+ char *dst;
+ char c;
+ int i;
+ int len;
+
+ if (!uniquenamespacename) {
+ strcpy(buf, "@unnamed@");
+ dst = buf + strlen(buf);
+
+ COS_FileGetFSSpecInfo(&cparamblkptr->mainFileSpec, NULL, NULL, filename);
+ src = (char *) &filename[1];
+ len = filename[0];
+ for (i = 0; i < len && dst < &buf[254]; i++) {
+ c = *(src++);
+ if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9'))
+ c = '_';
+ *(dst++) = c;
+ }
+
+ dst[0] = '@';
+ dst[1] = 0;
+ uniquenamespacename = GetHashNameNodeExport(buf);
+ }
+
+ return uniquenamespacename;
+}
+
+Boolean IsTempName(HashNameNode *name) {
+ return !name || (name->name[0] == '@') || (name->name[0] == '$');
+}
+
+static void CParser_SetCFMFlags(Object *object, DeclInfo *declinfo) {
+ if (declinfo && declinfo->exportflags)
+ object->flags |= declinfo->exportflags;
+
+ if (object->datatype == DDATA) {
+ if (copts.export)
+ object->flags |= OBJECT_FLAGS_40;
+ if (copts.internal)
+ object->flags |= OBJECT_FLAGS_10;
+ } else if (copts.internal) {
+ object->flags |= OBJECT_FLAGS_10;
+ } else {
+ if (copts.import)
+ object->flags |= OBJECT_FLAGS_20;
+ if (copts.export)
+ object->flags |= OBJECT_FLAGS_40;
+ if (copts.lib_export)
+ object->flags |= OBJECT_FLAGS_20 | OBJECT_FLAGS_40;
+ }
+}
+
+void CParser_UpdateObject(Object *object, DeclInfo *declinfo) {
+ if (declinfo && declinfo->section)
+ object->section = declinfo->section;
+
+ CParser_SetCFMFlags(object, declinfo);
+ CodeGen_UpdateObject(object);
+}
+
+Object *CParser_NewObject(DeclInfo *declinfo) {
+ Object *object = galloc(sizeof(Object));
+ memclrw(object, sizeof(Object));
+ CParser_SetCFMFlags(object, declinfo);
+ object->otype = OT_OBJECT;
+ object->access = ACCESSPUBLIC;
+ object->section = SECT_DEFAULT;
+ return object;
+}
+
+Object *CParser_NewLocalDataObject(DeclInfo *declinfo, Boolean add_to_locals) {
+ Object *object = lalloc(sizeof(Object));
+ memclrw(object, sizeof(Object));
+ object->otype = OT_OBJECT;
+ object->access = ACCESSPUBLIC;
+ object->datatype = DLOCAL;
+
+ if (declinfo) {
+ object->type = declinfo->thetype;
+ object->name = declinfo->name;
+ object->qual = declinfo->qual;
+ object->sclass = declinfo->storageclass;
+ }
+
+ if (add_to_locals) {
+ ObjectList *list = lalloc(sizeof(ObjectList));
+ list->object = object;
+ list->next = locals;
+ locals = list;
+ }
+
+ return object;
+}
+
+Object *CParser_NewGlobalDataObject(DeclInfo *declinfo) {
+ Object *object = galloc(sizeof(Object));
+ memclrw(object, sizeof(Object));
+ object->otype = OT_OBJECT;
+ object->access = ACCESSPUBLIC;
+ object->section = SECT_DEFAULT;
+ object->datatype = DDATA;
+ object->nspace = cscope_current;
+
+ if (declinfo) {
+ object->type = declinfo->thetype;
+ object->name = declinfo->name;
+ object->qual = declinfo->qual;
+ object->sclass = declinfo->storageclass;
+ if (copts.cplusplus && !declinfo->x4E)
+ object->qual |= Q_80000;
+ }
+
+ CParser_UpdateObject(object, declinfo);
+ return object;
+}
+
+Object *CParser_NewCompilerDefDataObject(void) {
+ Object *object = galloc(sizeof(Object));
+ memclrw(object, sizeof(Object));
+ object->otype = OT_OBJECT;
+ object->access = ACCESSPUBLIC;
+ object->section = SECT_DEFAULT;
+ object->datatype = DDATA;
+ object->nspace = cscope_root;
+
+ return object;
+}
+
+Object *CParser_NewFunctionObject(DeclInfo *declinfo) {
+ Object *object = galloc(sizeof(Object));
+ memclrw(object, sizeof(Object));
+ object->otype = OT_OBJECT;
+ object->access = ACCESSPUBLIC;
+ object->section = SECT_DEFAULT;
+ object->datatype = DFUNC;
+ object->nspace = cscope_current;
+
+ if (declinfo) {
+ object->type = declinfo->thetype;
+ object->name = declinfo->name;
+ object->qual = declinfo->qual;
+ object->sclass = declinfo->storageclass;
+ if (copts.cplusplus && !declinfo->x4E)
+ object->qual |= Q_80000;
+ }
+
+ CParser_UpdateObject(object, declinfo);
+ return object;
+}
+
+Object *CParser_NewCompilerDefFunctionObject(void) {
+ Object *object = galloc(sizeof(Object));
+ memclrw(object, sizeof(Object));
+ object->otype = OT_OBJECT;
+ object->access = ACCESSPUBLIC;
+ object->section = SECT_DEFAULT;
+ object->datatype = DFUNC;
+ object->nspace = cscope_root;
+ return object;
+}
+
+Object *CParser_NewAliasObject(Object *object, SInt32 offset) {
+ Object *alias = galloc(sizeof(Object));
+ *alias = *object;
+ alias->datatype = DALIAS;
+ alias->u.alias.object = object;
+ alias->u.alias.member = NULL;
+ alias->u.alias.offset = offset;
+ CScope_AddObject(cscope_current, alias->name, OBJ_BASE(alias));
+ return alias;
+}
+
+FuncArg *CParser_NewFuncArg(void) {
+ FuncArg *arg = galloc(sizeof(FuncArg));
+ memclrw(arg, sizeof(FuncArg));
+ return arg;
+}
+
+Type *atomtype(void) {
+ switch (tksize) {
+ default:
+#line 1145
+ CError_FATAL();
+ case ATOM_VOID: return &stvoid;
+ case ATOM_CHAR: return TYPE(&stchar);
+ case ATOM_WCHAR: return TYPE(&stwchar);
+ case ATOM_UCHAR: return TYPE(&stunsignedchar);
+ case ATOM_SHORT: return TYPE(&stsignedshort);
+ case ATOM_USHORT: return TYPE(&stunsignedshort);
+ case ATOM_INT: return TYPE(&stsignedint);
+ case ATOM_UINT: return TYPE(&stunsignedint);
+ case ATOM_LONG: return TYPE(&stsignedlong);
+ case ATOM_ULONG: return TYPE(&stunsignedlong);
+ case ATOM_LONGLONG: return TYPE(&stsignedlonglong);
+ case ATOM_ULONGLONG: return TYPE(&stunsignedlonglong);
+ case ATOM_FLOAT: return TYPE(&stfloat);
+ case ATOM_SHORTDOUBLE: return TYPE(&stshortdouble);
+ case ATOM_DOUBLE: return TYPE(&stdouble);
+ case ATOM_LONGDOUBLE: return TYPE(&stlongdouble);
+ }
+}
+
+Object *CParser_FindDeallocationObject(Type *type, FuncArg *args, Boolean flag1, Boolean flag2, Boolean *outflag) {
+ NameSpaceObjectList *list;
+ NameSpaceObjectList *scan;
+ NameSpaceObjectList mylist;
+ CScopeParseResult pr;
+ Boolean first_time;
+ Boolean retry_flag;
+ Type *sizet;
+ Object *obj;
+
+ list = NULL;
+ *outflag = 0;
+ if (IS_TYPE_CLASS(type) && !flag2) {
+ HashNameNode *name;
+ name = (flag1 && copts.array_new_delete) ? dela_fobj->name : delp_fobj->name;
+ if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) {
+ if (pr.obj_10) {
+ mylist.next = NULL;
+ mylist.object = pr.obj_10;
+ list = &mylist;
+ } else {
+#line 1202
+ CError_ASSERT(pr.nsol_14);
+ list = pr.nsol_14;
+ }
+ } else if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) {
+#line 1210
+ CError_ASSERT(!args && !flag1);
+ return delh_func;
+ }
+ }
+
+ first_time = 1;
+ retry_flag = flag1;
+ while (1) {
+ if (!args) {
+ for (scan = list; scan; scan = scan->next) {
+ obj = OBJECT(scan->object);
+ if (
+ obj->otype == OT_OBJECT &&
+ IS_TYPE_FUNC(obj->type) &&
+ TYPE_FUNC(obj->type)->args &&
+ !TYPE_FUNC(obj->type)->args->next &&
+ is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr))
+ )
+ return obj;
+ }
+
+#line 1231
+ CError_ASSERT(first_time);
+
+ sizet = CABI_GetSizeTType();
+ for (scan = list; scan; scan = scan->next) {
+ obj = OBJECT(scan->object);
+ if (
+ obj->otype == OT_OBJECT &&
+ IS_TYPE_FUNC(obj->type) &&
+ TYPE_FUNC(obj->type)->args &&
+ TYPE_FUNC(obj->type)->args->next &&
+ !TYPE_FUNC(obj->type)->args->next->next &&
+ is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) &&
+ TYPE_FUNC(obj->type)->args->next->type == sizet
+ ) {
+ *outflag = 1;
+ return obj;
+ }
+ }
+ } else {
+ for (scan = list; scan; scan = scan->next) {
+ obj = OBJECT(scan->object);
+ if (
+ obj->otype == OT_OBJECT &&
+ IS_TYPE_FUNC(obj->type) &&
+ TYPE_FUNC(obj->type)->args &&
+ TYPE_FUNC(obj->type)->args->next &&
+ is_arglistsame(TYPE_FUNC(obj->type)->args->next, args)
+ ) {
+ *outflag = 1;
+ return obj;
+ }
+ }
+
+ if (!first_time)
+ return NULL;
+ }
+
+ if (list)
+ CError_Warning(375, type, 0);
+
+ list = (retry_flag && copts.array_new_delete) ? &dela_fobj->first : &delp_fobj->first;
+ first_time = 0;
+ }
+}
+
+static Boolean oldstylecompatible(FuncArg *arg) {
+ if (copts.ignore_oldstyle)
+ return 1;
+
+ while (arg) {
+ if (arg == &elipsis)
+ return 0;
+ switch (arg->type->type) {
+ case TYPEINT:
+ if (TYPE_INTEGRAL(arg->type)->integral < IT_INT)
+ return 0;
+ break;
+ case TYPEFLOAT:
+ if (TYPE_INTEGRAL(arg->type)->integral < IT_DOUBLE)
+ return 0;
+ break;
+ }
+ arg = arg->next;
+ }
+
+ return 1;
+}
+
+static Boolean is_arglistequal(FuncArg *a, FuncArg *b) {
+ if (a == &oldstyle) {
+ if (b == &oldstyle)
+ return 1;
+ else
+ return oldstylecompatible(b);
+ } else {
+ if (b == &oldstyle)
+ return oldstylecompatible(a);
+ }
+
+ while (1) {
+ if (a == &elipsis || b == &elipsis)
+ return 1;
+
+ if (!a)
+ return !b;
+ if (!b)
+ return 0;
+
+ if (copts.mpwc_relax && !copts.cplusplus) {
+ if (!is_typeequal(a->type, b->type))
+ return 0;
+ } else {
+ if (!is_typesame(a->type, b->type))
+ return 0;
+ }
+
+ if (a->type->type == TYPEPOINTER && a->qual != b->qual)
+ return 0;
+
+ a = a->next;
+ b = b->next;
+ }
+}
+
+short is_memberpointerequal(Type *a, Type *b) {
+ FuncArg *arg_a;
+ FuncArg *arg_b;
+
+ if (a->type != b->type)
+ return 0;
+ if (!IS_TYPE_FUNC(a))
+ return is_typeequal(a, b);
+
+ if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
+ return 0;
+
+ if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
+ return 0;
+
+#line 1345
+ CError_ASSERT((arg_a = TYPE_FUNC(a)->args));
+ CError_ASSERT((arg_b = TYPE_FUNC(b)->args));
+
+ if (TYPE_FUNC(a)->flags & FUNC_FLAGS_80) {
+#line 1351
+ CError_ASSERT((arg_a = arg_a->next));
+ }
+
+ if (TYPE_FUNC(b)->flags & FUNC_FLAGS_80) {
+#line 1355
+ CError_ASSERT((arg_b = arg_b->next));
+ }
+
+ if (arg_a->qual != arg_b->qual)
+ return 0;
+
+ return is_arglistsame(arg_a->next, arg_b->next);
+}
+
+short is_typeequal(Type *a, Type *b) {
+restart:
+ if (a->type != b->type)
+ return 0;
+ switch (a->type) {
+ case TYPEVOID:
+ return 1;
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ case TYPECLASS:
+ return a == b;
+ case TYPESTRUCT:
+ return a == b;
+ case TYPEPOINTER:
+ if (TYPE_POINTER(a)->target == &stvoid || TYPE_POINTER(b)->target == &stvoid)
+ return 1;
+ a = TYPE_POINTER(a)->target;
+ b = TYPE_POINTER(b)->target;
+ if (copts.mpwc_relax && !copts.cplusplus)
+ return 1;
+ goto restart;
+ case TYPEMEMBERPOINTER:
+ if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2)
+ return 0;
+ return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1);
+ case TYPEARRAY:
+ if (a->size && b->size && a->size != b->size)
+ return 0;
+ a = TYPE_POINTER(a)->target;
+ b = TYPE_POINTER(b)->target;
+ goto restart;
+ case TYPEFUNC:
+ if (copts.cplusplus || !copts.cpp_extensions) {
+ if (copts.mpwc_relax && !copts.cplusplus) {
+ if (!is_typeequal(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
+ return 0;
+ } else {
+ if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
+ return 0;
+ }
+ if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
+ return 0;
+ }
+ return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args);
+ case TYPETEMPLATE:
+ return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b));
+ default:
+#line 1441
+ CError_FATAL();
+ return 0;
+ }
+}
+
+short iscpp_typeequal(Type *a, Type *b) {
+ restart:
+ if (a->type != b->type)
+ return 0;
+ switch (a->type) {
+ case TYPEVOID:
+ return 1;
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ case TYPECLASS:
+ return a == b;
+ case TYPESTRUCT:
+ return a == b;
+ case TYPEPOINTER:
+ if (TYPE_POINTER(b)->target == &stvoid) {
+ if (TYPE_POINTER(a)->target == &stvoid)
+ return 1;
+ else
+ return -1;
+ }
+ if (TYPE_POINTER(a)->target == &stvoid) {
+ illegalimplicitconversion = 1;
+ return 0;
+ }
+ a = TYPE_POINTER(a)->target;
+ b = TYPE_POINTER(b)->target;
+ goto restart;
+ case TYPEMEMBERPOINTER:
+ if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2)
+ return 0;
+ return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1);
+ case TYPEARRAY:
+ if (a->size && b->size && a->size != b->size)
+ return 0;
+ a = TYPE_POINTER(a)->target;
+ b = TYPE_POINTER(b)->target;
+ goto restart;
+ case TYPEFUNC:
+ if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
+ return 0;
+ if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
+ return 0;
+ return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args);
+ case TYPETEMPLATE:
+ return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b));
+ default:
+#line 1500
+ CError_FATAL();
+ return 0;
+ }
+}
+
+short CParser_CompareArgLists(FuncArg *a, FuncArg *b) {
+ Boolean r30;
+
+ r30 = 0;
+ if (a == &oldstyle) {
+ if (b == &oldstyle)
+ return 1;
+ else
+ return 2;
+ }
+ if (b == &oldstyle)
+ return 2;
+
+ while (1) {
+ if (a == &elipsis) {
+ if (b != &elipsis)
+ return 0;
+ break;
+ }
+ if (b == &elipsis)
+ return 0;
+
+ if (a == NULL) {
+ if (b)
+ return 0;
+ break;
+ }
+ if (b == NULL)
+ return 0;
+
+ if (a->type->type == TYPEPOINTER) {
+ if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type))) {
+ if (IS_TYPE_REFERENCE(b->type)) {
+ if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target))
+ return 0;
+ if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
+ return 0;
+ } else {
+ if (!copts.old_argmatch)
+ return 0;
+ if (!is_typesame(TYPE_POINTER(a->type)->target, b->type))
+ return 0;
+ if (b->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
+ return 0;
+ r30 = 1;
+ }
+ } else {
+ if (b->type->type == TYPEPOINTER) {
+ if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) {
+ if (!copts.old_argmatch)
+ return 0;
+ if (!is_typesame(a->type, TYPE_POINTER(b->type)->target))
+ return 0;
+ if (a->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
+ return 0;
+ r30 = 1;
+ } else {
+ if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target))
+ return 0;
+ if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+ } else {
+ if (b->type->type == TYPEPOINTER) {
+ if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) {
+ if (!copts.old_argmatch)
+ return 0;
+ if (!is_typesame(a->type, TYPE_POINTER(b->type)->target))
+ return 0;
+ r30 = 1;
+ } else {
+ return 0;
+ }
+ } else {
+ if (!is_typesame(a->type, b->type))
+ return 0;
+ }
+ }
+
+ a = a->next;
+ b = b->next;
+ }
+
+ if (r30)
+ return 2;
+ return 1;
+}
+
+Boolean is_arglistsame(FuncArg *a, FuncArg *b) {
+ if (a == &oldstyle) {
+ if (b == &oldstyle)
+ return 1;
+ else
+ return oldstylecompatible(b);
+ } else {
+ if (b == &oldstyle)
+ return oldstylecompatible(a);
+ }
+
+ while (1) {
+ if (!a || !b || a == &elipsis || b == &elipsis)
+ return a == b;
+
+ if (a->type->type == TYPEPOINTER) {
+ if (b->type->type != TYPEPOINTER ||
+ (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)) ||
+ !is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target) ||
+ IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type)) != IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type)))
+ return 0;
+ } else {
+ if (!is_typesame(a->type, b->type))
+ return 0;
+ }
+
+ a = a->next;
+ b = b->next;
+ }
+}
+
+short is_typesame(Type *a, Type *b) {
+restart:
+ if (a->type != b->type) {
+ if (IS_TYPE_TEMPLATE(a) && IS_TYPE_CLASS(b) && (TYPE_CLASS(b)->flags & CLASS_FLAGS_100))
+ return CTemplTool_IsSameTemplateType(b, a);
+ if (IS_TYPE_TEMPLATE(b) && IS_TYPE_CLASS(a) && (TYPE_CLASS(a)->flags & CLASS_FLAGS_100))
+ return CTemplTool_IsSameTemplateType(a, b);
+ return 0;
+ }
+
+ switch (a->type) {
+ case TYPEVOID:
+ return 1;
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ case TYPECLASS:
+ return a == b;
+ case TYPETEMPLATE:
+ return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b));
+ case TYPESTRUCT:
+ return a == b;
+ case TYPEPOINTER:
+ if ((TYPE_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)))
+ return 0;
+ a = TYPE_POINTER(a)->target;
+ b = TYPE_POINTER(b)->target;
+ goto restart;
+ case TYPEMEMBERPOINTER:
+ if (!is_typesame(TYPE_MEMBER_POINTER(a)->ty2, TYPE_MEMBER_POINTER(b)->ty2))
+ return 0;
+ if ((TYPE_MEMBER_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_MEMBER_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)))
+ return 0;
+ return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1);
+ case TYPEARRAY:
+ if (a->size != b->size)
+ return 0;
+ a = TYPE_POINTER(a)->target;
+ b = TYPE_POINTER(b)->target;
+ goto restart;
+ case TYPEFUNC:
+ if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
+ return 0;
+ if (TYPE_FUNC(a)->qual != TYPE_FUNC(b)->qual)
+ return 0;
+ if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
+ return 0;
+ return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args);
+ default:
+#line 1709
+ CError_FATAL();
+ return 0;
+ }
+}
+
+Type *CParser_GetBoolType(void) {
+ if (copts.cplusplus && copts.booltruefalse)
+ return TYPE(&stbool);
+ else
+ return TYPE(&stsignedint);
+}
+
+Type *CParser_GetWCharType(void) {
+ if (copts.cplusplus && copts.wchar_type)
+ return TYPE(&stwchar);
+ else
+ return TYPE(&stsignedint);
+}
+
+short CParser_GetOperator(ENodeType t) {
+ switch (t) {
+ default:
+#line 1748
+ CError_FATAL();
+ case EMONMIN: return '-';
+ case EBINNOT: return '~';
+ case ELOGNOT: return '!';
+ case EADD: return '+';
+ case ESUB: return '-';
+ case EMUL: return '*';
+ case EDIV: return '/';
+ case EMODULO: return '%';
+ case EAND: return '&';
+ case EXOR: return '^';
+ case EOR: return '|';
+ case ESHL: return TK_SHL;
+ case ESHR: return TK_SHR;
+ case ELESS: return '<';
+ case EGREATER: return '>';
+ case ELESSEQU: return TK_LESS_EQUAL;
+ case EGREATEREQU: return TK_GREATER_EQUAL;
+ case EEQU: return TK_LOGICAL_EQ;
+ case ENOTEQU: return TK_LOGICAL_NE;
+ }
+}
+
+Boolean CParser_IsMoreCVQualified(UInt32 a, UInt32 b) {
+ if ((a & Q_CONST) && !(b & Q_CONST)) {
+ return ((a & Q_VOLATILE) || !(b & Q_VOLATILE));
+ } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) {
+ return ((a & Q_CONST) || !(b & Q_CONST));
+ }
+ return 0;
+}
+
+Boolean CParser_IsSameOrMoreCVQualified(UInt32 a, UInt32 b) {
+ if ((a & (Q_CONST | Q_VOLATILE)) == (b & (Q_CONST | Q_VOLATILE)))
+ return 1;
+
+ if ((a & Q_CONST) && !(b & Q_CONST)) {
+ return ((a & Q_VOLATILE) || !(b & Q_VOLATILE));
+ } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) {
+ return ((a & Q_CONST) || !(b & Q_CONST));
+ }
+ return 0;
+}
+
+Boolean is_unsigned(Type *type) {
+ if (IS_TYPE_ENUM(type))
+ type = TYPE_ENUM(type)->enumtype;
+
+ if (
+ (type == TYPE(&stunsignedchar)) ||
+ (type == TYPE(&stunsignedshort)) ||
+ (type == TYPE(&stunsignedint)) ||
+ (type == TYPE(&stunsignedlong)) ||
+ (type == TYPE(&stunsignedlonglong)) ||
+ (type == TYPE(&stbool)) ||
+ (copts.unsignedchars && (type == TYPE(&stchar))) ||
+ (type->type == TYPEPOINTER))
+ return 1;
+
+ return 0;
+}
+
+StructMember *ismember(TypeStruct *tstruct, HashNameNode *name) {
+ StructMember *member;
+
+ for (member = tstruct->members; member; member = member->next) {
+ if (member->name == name)
+ return member;
+ }
+
+ return NULL;
+}
+
+void appendmember(TypeStruct *tstruct, StructMember *member) {
+ StructMember *last;
+
+ if (!tstruct->members) {
+ tstruct->members = member;
+ return;
+ }
+
+ for (last = tstruct->members; last->next; last = last->next) {}
+ last->next = member;
+}
+
+static void CParser_InsertTryBlock(ParserTryBlock *block) {
+ block->cscope_current = cscope_current;
+ block->cscope_currentclass = cscope_currentclass;
+ block->cscope_currentfunc = cscope_currentfunc;
+ block->ctempl_curinstance = ctempl_curinstance;
+ block->cerror_locktoken = cerror_locktoken;
+ block->cscope_is_member_func = cscope_is_member_func;
+ block->next = trychain;
+ trychain = block;
+}
+
+static void CParser_RemoveTryBlock(ParserTryBlock *block) {
+ cscope_current = block->cscope_current;
+ cscope_currentclass = block->cscope_currentclass;
+ cscope_currentfunc = block->cscope_currentfunc;
+ ctempl_curinstance = block->ctempl_curinstance;
+ cerror_locktoken = block->cerror_locktoken;
+ cscope_is_member_func = block->cscope_is_member_func;
+ trychain = block->next;
+}
+
+static Boolean TryIsDeclaration(Boolean flag1, Boolean flag2, Boolean flag3, short token) {
+ Boolean result;
+ DeclInfo declinfo;
+ struct ParserTryBlock tryblock;
+
+ switch (tk) {
+ case TK_IDENTIFIER:
+ case TK_COLON_COLON:
+ break;
+ case TK_VOID:
+ case TK_CHAR:
+ case TK_SHORT:
+ case TK_INT:
+ case TK_LONG:
+ case TK_FLOAT:
+ case TK_DOUBLE:
+ case TK_SIGNED:
+ case TK_UNSIGNED:
+ case TK_UNK_113:
+ case TK_UNK_114:
+ case TK_UNK_115:
+ case TK_UNK_116:
+ case TK_UNK_117:
+ case TK_UNK_118:
+ case TK_UNK_119:
+ case TK_UNK_11A:
+ case TK_BOOL:
+ case TK_WCHAR_T:
+ if (lookahead() != '(')
+ return 1;
+ break;
+ default:
+ return 1;
+ }
+
+ result = 0;
+ CParser_InsertTryBlock(&tryblock);
+ if (setjmp(tryblock.jmpbuf) == 0) {
+ memclrw(&declinfo, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&declinfo, 0);
+ if (!(IS_TYPE_TEMPLATE(declinfo.thetype) && TYPE_TEMPLATE(declinfo.thetype)->dtype == TEMPLDEP_QUALNAME && !declinfo.x53 && !declinfo.x49)) {
+ if (flag1) {
+ declinfo.x46 = flag3;
+ scandeclarator(&declinfo);
+ if (!(flag2 && declinfo.name)) {
+ if (!token) {
+ if (tk == ';' || tk == ',' || tk == '=' || tk == '(' || tk == ')' || tk == '>')
+ result = 1;
+ } else {
+ result = (tk == token);
+ }
+ }
+ } else {
+ result = 1;
+ }
+ }
+ }
+
+ CParser_RemoveTryBlock(&tryblock);
+ return result;
+}
+
+Boolean isdeclaration(UInt8 flag1, UInt8 flag2, UInt8 flag3, short token) {
+ SInt32 state;
+
+ if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) {
+ if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector")))
+ return 0;
+ } else {
+ if (!copts.cplusplus)
+ return 1;
+ }
+
+ CPrep_TokenStreamGetState(&state);
+ if (TryIsDeclaration(flag1, flag2, flag3, token)) {
+ CPrep_TokenStreamSetCurState(&state);
+ return 1;
+ } else {
+ CPrep_TokenStreamSetCurState(&state);
+ return 0;
+ }
+}
+
+Boolean islookaheaddeclaration(void) {
+ SInt32 state;
+
+ CPrep_TokenStreamGetState(&state);
+ tk = lex();
+ if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) {
+ if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) {
+ CPrep_TokenStreamSetCurState(&state);
+ return 0;
+ }
+ } else {
+ if (!copts.cplusplus) {
+ CPrep_TokenStreamSetCurState(&state);
+ return 1;
+ }
+ }
+
+ if (TryIsDeclaration(1, 1, 0, ')')) {
+ CPrep_TokenStreamSetCurState(&state);
+ return 1;
+ } else {
+ CPrep_TokenStreamSetCurState(&state);
+ return 0;
+ }
+}
+
+Type *CParser_ParseTypeID(UInt32 *qual, Boolean *flag) {
+ SInt32 state;
+ DeclInfo di;
+ struct ParserTryBlock tryblock;
+
+ memclrw(&di, sizeof(DeclInfo));
+ CPrep_TokenStreamGetState(&state);
+ CParser_InsertTryBlock(&tryblock);
+
+ if (setjmp(tryblock.jmpbuf) == 0) {
+ if (copts.cplusplus)
+ di.x55 = 1;
+
+ if (flag) {
+ di.x56 = 1;
+ *flag = 0;
+ }
+
+ CParser_GetDeclSpecs(&di, 0);
+ if (di.x57 && IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_FLAGS_100)) {
+ CParser_RemoveTryBlock(&tryblock);
+ *qual = di.qual;
+ *flag = 1;
+ return di.thetype;
+ }
+
+ if (flag && IS_TYPE_TEMPLATE(di.thetype) && TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_ARGUMENT &&
+ TYPE_TEMPLATE(di.thetype)->u.pid.type == TPT_TEMPLATE) {
+ CParser_RemoveTryBlock(&tryblock);
+ *qual = di.qual;
+ *flag = 1;
+ return di.thetype;
+ }
+
+ scandeclarator(&di);
+ if (!di.name) {
+ CParser_RemoveTryBlock(&tryblock);
+ *qual = di.qual;
+ return di.thetype;
+ }
+ }
+
+ CPrep_TokenStreamSetCurState(&state);
+ CParser_RemoveTryBlock(&tryblock);
+ return 0;
+}
+
+Boolean CParser_TryFuncDecl(void) {
+ Boolean result;
+ SInt32 state;
+ DeclInfo di;
+ struct ParserTryBlock tryblock;
+
+ result = 0;
+ CPrep_TokenStreamGetState(&state);
+ CParser_InsertTryBlock(&tryblock);
+
+ if (setjmp(tryblock.jmpbuf) == 0) {
+ memclrw(&di, sizeof(DeclInfo));
+ di.thetype = &stvoid;
+ scandeclarator(&di);
+
+ if (IS_TYPE_FUNC(di.thetype))
+ result = 1;
+ }
+
+ CParser_RemoveTryBlock(&tryblock);
+ CPrep_TokenStreamSetCurState(&state);
+ return result;
+}
+
+Boolean CParser_TryParamList(Boolean flag) {
+ Boolean result;
+ SInt32 state;
+ struct ParserTryBlock tryblock;
+
+ result = 0;
+ CPrep_TokenStreamGetState(&state);
+
+ switch ((tk = lex())) {
+ case ')':
+ case TK_ELLIPSIS:
+ result = 1;
+ break;
+ default:
+ CParser_InsertTryBlock(&tryblock);
+ if (setjmp(tryblock.jmpbuf) == 0) {
+ if (CFunc_ParseFakeArgList(flag) || tk == ')')
+ result = 1;
+ }
+ CParser_RemoveTryBlock(&tryblock);
+ break;
+ }
+
+ CPrep_TokenStreamSetCurState(&state);
+ return result;
+}
+
+Type *CParser_RemoveTopMostQualifiers(Type *type, UInt32 *qual) {
+ switch (type->type) {
+ case TYPEARRAY:
+ TYPE_POINTER(type)->target = CParser_RemoveTopMostQualifiers(TYPE_POINTER(type)->target, qual);
+ return type;
+ case TYPEPOINTER:
+ if (TYPE_POINTER(type)->qual & Q_CONST) {
+ TypePointer *newtype = galloc(sizeof(TypePointer));
+ *newtype = *TYPE_POINTER(type);
+ newtype->qual = 0;
+ return TYPE(newtype);
+ }
+ return type;
+ case TYPEMEMBERPOINTER:
+ if (TYPE_MEMBER_POINTER(type)->qual & Q_CONST) {
+ TypeMemberPointer *newtype = galloc(sizeof(TypeMemberPointer));
+ *newtype = *TYPE_MEMBER_POINTER(type);
+ newtype->qual = 0;
+ return TYPE(newtype);
+ }
+ return type;
+ default:
+ *qual = 0;
+ return type;
+ }
+}
+
+UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual) {
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+
+ switch (type->type) {
+ case TYPEPOINTER:
+ qual = TYPE_POINTER(type)->qual;
+ break;
+ case TYPEMEMBERPOINTER:
+ qual = TYPE_MEMBER_POINTER(type)->qual;
+ break;
+ }
+
+ return qual;
+}
+
+UInt32 CParser_GetCVTypeQualifiers(Type *type, UInt32 qual) {
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+
+ switch (type->type) {
+ case TYPEPOINTER:
+ qual = TYPE_POINTER(type)->qual;
+ break;
+ case TYPEMEMBERPOINTER:
+ qual = TYPE_MEMBER_POINTER(type)->qual;
+ break;
+ }
+
+ return qual & (Q_CONST | Q_VOLATILE);
+}
+
+Boolean CParser_IsConst(Type *type, UInt32 qual) {
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+
+ switch (type->type) {
+ case TYPEPOINTER:
+ qual = TYPE_POINTER(type)->qual;
+ break;
+ case TYPEMEMBERPOINTER:
+ qual = TYPE_MEMBER_POINTER(type)->qual;
+ break;
+ }
+
+ return qual & Q_CONST;
+}
+
+Boolean CParser_IsVolatile(Type *type, UInt32 qual) {
+ while (IS_TYPE_ARRAY(type))
+ type = TYPE_POINTER(type)->target;
+
+ switch (type->type) {
+ case TYPEPOINTER:
+ qual = TYPE_POINTER(type)->qual;
+ break;
+ case TYPEMEMBERPOINTER:
+ qual = TYPE_MEMBER_POINTER(type)->qual;
+ break;
+ }
+
+ return (qual & Q_VOLATILE) ? 1 : 0;
+}
+
+Boolean is_const_object(Object *obj) {
+ return CParser_IsConst(obj->type, obj->qual);
+}
+
+Boolean is_volatile_object(Object *obj) {
+ return CParser_IsVolatile(obj->type, obj->qual);
+}
+
+Boolean CParserIsConstExpr(ENode *expr) {
+ return CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS);
+}
+
+Boolean CParserIsVolatileExpr(ENode *expr) {
+ return CParser_IsVolatile(expr->rtype, expr->flags & ENODE_FLAG_QUALS);
+}
+
+Boolean CParser_HasInternalLinkage(Object *obj) {
+ NameSpace *nspace;
+
+ for (nspace = obj->nspace; nspace; nspace = nspace->parent) {
+ if (nspace->is_unnamed)
+ return 1;
+ }
+
+ if (obj->datatype == DLOCAL)
+ return 1;
+ if (obj->qual & (Q_20000 | Q_OVERLOAD))
+ return 0;
+ if (obj->sclass == OBJECT_SCLASS_102)
+ return 1;
+
+ if (obj->qual & Q_INLINE)
+ obj->qual |= Q_20000;
+ return 0;
+}
+
+Boolean CParser_HasInternalLinkage2(Object *obj) {
+ if (obj->datatype == DLOCAL)
+ return 1;
+ if (obj->qual & (Q_20000 | Q_OVERLOAD))
+ return 0;
+ if (obj->sclass == OBJECT_SCLASS_102)
+ return 1;
+
+ if (obj->qual & Q_INLINE)
+ obj->qual |= Q_20000;
+ return 0;
+}
+
+Boolean CParser_IsVirtualFunction(Object *obj, TypeClass **tclass, SInt32 *index) {
+ if (obj->datatype == DVFUNC) {
+ *tclass = TYPE_METHOD(obj->type)->theclass;
+ *index = TYPE_METHOD(obj->type)->x1E;
+ return 1;
+ }
+
+ return 0;
+}
+
+Boolean is_pascal_object(Object *obj) {
+ return IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_PASCAL);
+}
+
+Boolean is_cfm_type(Type *type) {
+ return 0;
+}
+
+Boolean CParser_IsVTableObject(Object *obj) {
+ return
+ obj->datatype == DDATA &&
+ obj->nspace &&
+ obj->nspace->theclass &&
+ obj->nspace->theclass->vtable &&
+ obj->nspace->theclass->vtable->object == obj;
+}
+
+static Type *getthetype(short token, short size, short signedness) {
+ switch (token) {
+ case 0:
+ case TK_INT:
+ if (signedness == 1) {
+ switch (size) {
+ case 1: return TYPE(&stunsignedshort);
+ case 2: return TYPE(&stunsignedlong);
+ case 3: return TYPE(&stunsignedlonglong);
+ default: return TYPE(&stunsignedint);
+ }
+ } else {
+ switch (size) {
+ case 1: return TYPE(&stsignedshort);
+ case 2: return TYPE(&stsignedlong);
+ case 3: return TYPE(&stsignedlonglong);
+ default: return TYPE(&stsignedint);
+ }
+ }
+ case TK_BOOL:
+ return TYPE(&stbool);
+ case TK_WCHAR_T:
+ return TYPE(&stwchar);
+ case TK_CHAR:
+ switch (signedness) {
+ case 1: return TYPE(&stunsignedchar);
+ default: return TYPE(&stchar);
+ case -1: return TYPE(&stsignedchar);
+ }
+ case TK_DOUBLE:
+ switch (size) {
+ case 1: return TYPE(&stshortdouble);
+ case 2: return TYPE(&stlongdouble);
+ default: return TYPE(&stdouble);
+ }
+ case TK_FLOAT:
+ return TYPE(&stfloat);
+ case TK_VOID:
+ return TYPE(&stvoid);
+ default:
+ CError_Error(121);
+ return TYPE(&stvoid);
+ }
+}
+
+void TypedefDeclInfo(DeclInfo *declinfo, Type *type, UInt32 qual) {
+ if (type->type == TYPEPOINTER) {
+ if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(type))) {
+ declinfo->thetype = type;
+ declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST);
+ declinfo->qual |= qual;
+ return;
+ }
+
+ declinfo->thetype = galloc(sizeof(TypePointer));
+ *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type);
+ TYPE_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST);
+ declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST);
+ declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST);
+ } else if (type->type == TYPEMEMBERPOINTER) {
+ declinfo->thetype = galloc(sizeof(TypeMemberPointer));
+ *TYPE_MEMBER_POINTER(declinfo->thetype) = *TYPE_MEMBER_POINTER(type);
+ TYPE_MEMBER_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST);
+ declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST);
+ declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST);
+ } else {
+ declinfo->thetype = type;
+ declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST);
+ if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size) {
+ declinfo->thetype = galloc(sizeof(TypePointer));
+ *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type);
+ }
+ }
+ declinfo->x49 = 1;
+}
+
+static void CParser_ParseAttributeFunctionSummary(DeclInfo *declinfo) {
+ Boolean flag;
+
+ if ((tk = lex()) != '(') {
+ CError_Error(114);
+ return;
+ }
+
+ flag = 1;
+ tk = lookahead();
+ while (tk == TK_IDENTIFIER) {
+ if (flag && !strcmp(tkidentifier->name, "entry_points_to")) {
+ PointerAnalysis_ParseEntryPointsToSpecifier(declinfo);
+ } else if (!strcmp(tkidentifier->name, "exit_points_to")) {
+ PointerAnalysis_ParseExitPointsToSpecifier(declinfo);
+ flag = 0;
+ } else if (!strcmp(tkidentifier->name, "function_modifies")) {
+ PointerAnalysis_ParseFunctionModifiesSpecifier(declinfo);
+ flag = 0;
+ } else {
+ lex();
+ CError_Error(121);
+ return;
+ }
+
+ tk = lookahead();
+ if (tk == ',') {
+ lex();
+ tk = lookahead();
+ }
+ }
+
+ lex();
+ if (tk != ')')
+ CError_Error(121);
+}
+
+void CParser_ParseAttribute(Type *type, DeclInfo *declinfo) {
+ CInt64 val64;
+ SInt32 val;
+
+ do {
+ if ((tk = lex()) != '(') {
+ CError_Error(121);
+ return;
+ }
+ if ((tk = lex()) != '(') {
+ CError_Error(121);
+ return;
+ }
+ if ((tk = lex()) != TK_IDENTIFIER && tk != TK_CONST) {
+ CError_Error(121);
+ return;
+ }
+
+ if (!strcmp(tkidentifier->name, "aligned") || !strcmp(tkidentifier->name, "__aligned__")) {
+ if ((tk = lex()) != '(') {
+ CError_Error(121);
+ return;
+ }
+
+ tk = lex();
+ val64 = CExpr_IntegralConstExpr();
+ switch ((val = CInt64_GetULong(&val64))) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 0x10:
+ case 0x20:
+ case 0x40:
+ case 0x80:
+ case 0x100:
+ case 0x200:
+ case 0x400:
+ case 0x800:
+ case 0x1000:
+ case 0x2000:
+ break;
+ default:
+ CError_Error(124);
+ return;
+ }
+ if (type) {
+ if (IS_TYPE_STRUCT(type)) {
+ if (val > TYPE_STRUCT(type)->align) {
+ TYPE_STRUCT(type)->align = val;
+ type->size += CABI_StructSizeAlignValue(type, type->size);
+ }
+ } else if (IS_TYPE_CLASS(type)) {
+ if (val > TYPE_CLASS(type)->align) {
+ TYPE_CLASS(type)->align = val;
+ type->size += CABI_StructSizeAlignValue(type, type->size);
+ }
+ } else {
+ CError_Error(149);
+ }
+ } else if (declinfo) {
+ declinfo->qual &= ~Q_ALIGNED_MASK;
+ switch (val) {
+ case 1:
+ declinfo->qual |= Q_ALIGNED_1;
+ break;
+ case 2:
+ declinfo->qual |= Q_ALIGNED_2;
+ break;
+ case 4:
+ declinfo->qual |= Q_ALIGNED_4;
+ break;
+ case 8:
+ declinfo->qual |= Q_ALIGNED_8;
+ break;
+ case 16:
+ declinfo->qual |= Q_ALIGNED_16;
+ break;
+ case 32:
+ declinfo->qual |= Q_ALIGNED_32;
+ break;
+ case 64:
+ declinfo->qual |= Q_ALIGNED_64;
+ break;
+ case 128:
+ declinfo->qual |= Q_ALIGNED_128;
+ break;
+ case 256:
+ declinfo->qual |= Q_ALIGNED_256;
+ break;
+ case 512:
+ declinfo->qual |= Q_ALIGNED_512;
+ break;
+ case 1024:
+ declinfo->qual |= Q_ALIGNED_1024;
+ break;
+ case 2048:
+ declinfo->qual |= Q_ALIGNED_2048;
+ break;
+ case 4096:
+ declinfo->qual |= Q_ALIGNED_4096;
+ break;
+ case 8192:
+ declinfo->qual |= Q_ALIGNED_8192;
+ break;
+ default:
+#line 2779
+ CError_FATAL();
+ break;
+ }
+ } else {
+ CError_Error(359);
+ }
+
+ if (tk != ')') {
+ CError_Error(121);
+ return;
+ }
+ } else if (!strcmp(tkidentifier->name, "nothrow") || !strcmp(tkidentifier->name, "__nothrow__")) {
+ if (declinfo && declinfo->thetype && IS_TYPE_FUNC(declinfo->thetype))
+ TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_NOTHROW;
+ else
+ CError_Error(359);
+ } else if (!strcmp("function_summary", tkidentifier->name)) {
+ CParser_ParseAttributeFunctionSummary(declinfo);
+ } else if (!strcmp(tkidentifier->name, "packed") || !strcmp(tkidentifier->name, "__packed__")) {
+ CError_Error(359);
+ } else if (!strcmp(tkidentifier->name, "unused") || !strcmp(tkidentifier->name, "__unused__")) {
+ } else if (!strcmp(tkidentifier->name, "noreturn") || !strcmp(tkidentifier->name, "__noreturn__")) {
+ } else if (tk == TK_CONST || !strcmp(tkidentifier->name, "__const__")) {
+ } else if (!strcmp(tkidentifier->name, "format") || !strcmp(tkidentifier->name, "__format__")) {
+ CError_Warning(359);
+ if ((tk = lex()) != '(') {
+ CError_Warning(114);
+ return;
+ }
+ tk = lex();
+ if ((tk = lex()) != ',') {
+ CError_Warning(116);
+ return;
+ }
+ tk = lex();
+ if ((tk = lex()) != ',') {
+ CError_Warning(116);
+ return;
+ }
+ tk = lex();
+ if ((tk = lex()) != ')') {
+ CError_Warning(115);
+ return;
+ }
+ } else if (!strcmp(tkidentifier->name, "mode") || !strcmp(tkidentifier->name, "__mode__")) {
+ CError_Warning(359);
+ if ((tk = lex()) != '(') {
+ CError_Warning(114);
+ return;
+ }
+ tk = lex();
+ if ((tk = lex()) != ')') {
+ CError_Warning(115);
+ return;
+ }
+ } else {
+ CError_Error(359);
+ }
+
+ if ((tk = lex()) != ')') {
+ CError_Error(121);
+ return;
+ }
+ if ((tk = lex()) != ')') {
+ CError_Error(121);
+ return;
+ }
+ tk = lex();
+ } while (tk == TK_UU_ATTRIBUTE_UU);
+}
+
+static void CParser_ParseTypeOf(DeclInfo *declinfo) {
+ DeclInfo subdi;
+ ENode *expr;
+
+ if ((tk = lex()) == '(' && islookaheaddeclaration()) {
+ tk = lex();
+
+ memclrw(&subdi, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&subdi, 0);
+ scandeclarator(&subdi);
+ if (subdi.name)
+ CError_Error(121);
+
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+
+ TypedefDeclInfo(declinfo, subdi.thetype, subdi.qual);
+ } else {
+ expr = unary_expression();
+ if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD))
+ CError_Error(144);
+ TypedefDeclInfo(declinfo, expr->rtype, expr->flags & ENODE_FLAG_QUALS);
+ }
+}
+
+void CParser_ParseDeclSpec(DeclInfo *declinfo, Boolean flag) {
+ if ((tk = lex()) != TK_IDENTIFIER) {
+ if (tk != TK_EXPORT)
+ CError_Error(107);
+ else
+ declinfo->exportflags |= EXPORT_FLAGS_EXPORT;
+ } else if (!strcmp("internal", tkidentifier->name)) {
+ declinfo->exportflags |= EXPORT_FLAGS_INTERNAL;
+ } else if (!strcmp("import", tkidentifier->name) || !strcmp("dllimport", tkidentifier->name)) {
+ declinfo->exportflags |= EXPORT_FLAGS_IMPORT;
+ } else if (!strcmp("export", tkidentifier->name) || !strcmp("dllexport", tkidentifier->name)) {
+ declinfo->exportflags |= EXPORT_FLAGS_EXPORT;
+ } else if (!strcmp("lib_export", tkidentifier->name)) {
+ declinfo->exportflags |= EXPORT_FLAGS_IMPORT | EXPORT_FLAGS_EXPORT;
+ } else if (!strcmp("weak", tkidentifier->name)) {
+ declinfo->qual |= Q_OVERLOAD;
+ } else {
+ CodeGen_ParseDeclSpec(tkidentifier, declinfo);
+ }
+}
+
+static int CParser_GetVectorDeclSpec(Type **type) {
+ tk = lex();
+ switch (tk) {
+ case TK_CHAR:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ *type = TYPE(&stvectorboolchar);
+ tk = lex();
+ return 1;
+ case TK_UNSIGNED:
+ *type = TYPE(&stvectorunsignedchar);
+ tk = lex();
+ return 1;
+ case TK_SIGNED:
+ *type = TYPE(&stvectorsignedchar);
+ tk = lex();
+ return 1;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ *type = TYPE(&stvectorboolchar);
+ tk = lex();
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_SIGNED:
+ tk = lex();
+ switch (tk) {
+ case TK_CHAR:
+ *type = TYPE(&stvectorsignedchar);
+ tk = lex();
+ return 1;
+ case TK_SHORT:
+ *type = TYPE(&stvectorsignedshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorsignedlong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_INT:
+ tk = lex();
+ switch (tk) {
+ case TK_SHORT:
+ *type = TYPE(&stvectorsignedshort);
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorsignedlong);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorsignedlong);
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_UNSIGNED:
+ tk = lex();
+ switch (tk) {
+ case TK_CHAR:
+ *type = TYPE(&stvectorunsignedchar);
+ tk = lex();
+ return 1;
+ case TK_SHORT:
+ *type = TYPE(&stvectorunsignedshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorunsignedlong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_INT:
+ tk = lex();
+ switch (tk) {
+ case TK_SHORT:
+ *type = TYPE(&stvectorunsignedshort);
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorunsignedlong);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorunsignedlong);
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_BOOL:
+ tk = lex();
+ switch (tk) {
+ case TK_CHAR:
+ *type = TYPE(&stvectorboolchar);
+ tk = lex();
+ return 1;
+ case TK_SHORT:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_INT:
+ tk = lex();
+ switch (tk) {
+ case TK_SHORT:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorboollong);
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_SHORT:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_SIGNED:
+ *type = TYPE(&stvectorsignedshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_UNSIGNED:
+ *type = TYPE(&stvectorunsignedshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_INT:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_SIGNED:
+ *type = TYPE(&stvectorsignedshort);
+ tk = lex();
+ return 1;
+ case TK_UNSIGNED:
+ *type = TYPE(&stvectorunsignedshort);
+ tk = lex();
+ return 1;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_LONG:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_SIGNED:
+ *type = TYPE(&stvectorsignedlong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_UNSIGNED:
+ *type = TYPE(&stvectorunsignedlong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_INT:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ case TK_SIGNED:
+ *type = TYPE(&stvectorsignedlong);
+ tk = lex();
+ return 1;
+ case TK_UNSIGNED:
+ *type = TYPE(&stvectorunsignedlong);
+ tk = lex();
+ return 1;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_INT:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ tk = lex();
+ switch (tk) {
+ case TK_SHORT:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorboollong);
+ return 1;
+ }
+ case TK_SIGNED:
+ tk = lex();
+ switch (tk) {
+ case TK_SHORT:
+ *type = TYPE(&stvectorsignedshort);
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorsignedlong);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorsignedlong);
+ return 1;
+ }
+ case TK_UNSIGNED:
+ tk = lex();
+ switch (tk) {
+ case TK_SHORT:
+ *type = TYPE(&stvectorunsignedshort);
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorunsignedlong);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorunsignedlong);
+ return 1;
+ }
+ case TK_SHORT:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ return 1;
+ case TK_SIGNED:
+ *type = TYPE(&stvectorsignedshort);
+ tk = lex();
+ return 1;
+ case TK_UNSIGNED:
+ *type = TYPE(&stvectorunsignedshort);
+ tk = lex();
+ return 1;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ return 1;
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_LONG:
+ tk = lex();
+ switch (tk) {
+ case TK_BOOL:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ case TK_SIGNED:
+ *type = TYPE(&stvectorsignedlong);
+ tk = lex();
+ return 1;
+ case TK_UNSIGNED:
+ *type = TYPE(&stvectorunsignedlong);
+ tk = lex();
+ return 1;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ }
+ }
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("bool")) {
+ tk = lex();
+ switch (tk) {
+ case TK_LONG:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ case TK_SHORT:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorboolshort);
+ return 1;
+ }
+ }
+ default:
+ CError_Error(121);
+ }
+ break;
+ case TK_FLOAT:
+ *type = TYPE(&stvectorfloat);
+ tk = lex();
+ return 1;
+ case TK_IDENTIFIER:
+ if (tkidentifier == GetHashNameNode("pixel") || tkidentifier == GetHashNameNode("__pixel")) {
+ *type = TYPE(&stvectorpixel);
+ tk = lex();
+ return 1;
+ }
+ if (tkidentifier == GetHashNameNode("bool")) {
+ tk = lex();
+ switch (tk) {
+ case TK_CHAR:
+ *type = TYPE(&stvectorboolchar);
+ tk = lex();
+ return 1;
+ case TK_SHORT:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ if (tk == TK_INT)
+ tk = lex();
+ return 1;
+ case TK_INT:
+ tk = lex();
+ switch (tk) {
+ case TK_SHORT:
+ *type = TYPE(&stvectorboolshort);
+ tk = lex();
+ return 1;
+ case TK_LONG:
+ *type = TYPE(&stvectorboollong);
+ tk = lex();
+ return 1;
+ default:
+ *type = TYPE(&stvectorboollong);
+ return 1;
+ }
+ }
+ }
+ default:
+ CError_Error(121);
+ }
+
+ return 0;
+}
+
+Boolean CParser_CheckTemplateClassUsage(TemplClass *tmclass, Boolean flag) {
+ NameSpace *nspace;
+
+ if (tmclass->templ__params) {
+ nspace = cscope_current;
+ while (1) {
+ if (!nspace) {
+ if (flag)
+ CError_Error(230);
+ return 0;
+ }
+ if (nspace->theclass == TYPE_CLASS(tmclass))
+ break;
+ nspace = nspace->parent;
+ }
+ }
+
+ return 1;
+}
+
+static Boolean CParser_IsAltiVecPrefix(void) {
+ HashNameNode *save = tkidentifier;
+
+ switch (lookahead()) {
+ case TK_CHAR:
+ case TK_SHORT:
+ case TK_INT:
+ case TK_LONG:
+ case TK_FLOAT:
+ case TK_SIGNED:
+ case TK_UNSIGNED:
+ case TK_BOOL:
+ return 1;
+ case TK_IDENTIFIER:
+ if (!strcmp(tkidentifier->name, "bool") || !strcmp(tkidentifier->name, "pixel") || !strcmp(tkidentifier->name, "__pixel"))
+ return 1;
+ }
+
+ tkidentifier = save;
+ return 0;
+}
+
+void CParser_GetDeclSpecs(DeclInfo *di, Boolean flag) {
+ short typesize;
+ short signedness;
+ short typetoken;
+ Boolean r24;
+ Boolean r23;
+ SInt32 state;
+ CScopeParseResult pr;
+
+ di->fileoffsetinfo.file = CPrep_BrowserCurrentFile();
+ CPrep_BrowserFilePosition(
+ (CPrepFileInfo **) &di->fileoffsetinfo.tokenline,
+ &di->fileoffsetinfo.tokenoffset);
+
+ r24 = 1;
+ r23 = copts.cplusplus;
+ typetoken = 0;
+ signedness = 0;
+ typesize = 0;
+
+restart:
+ switch (tk) {
+ case TK_AUTO:
+ case TK_REGISTER:
+ case TK_STATIC:
+ case TK_EXTERN:
+ case TK_TYPEDEF:
+ case TK_MUTABLE:
+ if (di->storageclass)
+ CError_Error(121);
+ di->storageclass = tk;
+ break;
+ case TK_CONST:
+ if (di->thetype) {
+ if (di->thetype->type == TYPEPOINTER) {
+ if (TYPE_POINTER(di->thetype)->qual & Q_CONST)
+ CError_QualifierCheck(Q_CONST);
+ TYPE_POINTER(di->thetype)->qual |= Q_CONST;
+ break;
+ } else if (di->thetype->type == TYPEMEMBERPOINTER) {
+ if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_CONST)
+ CError_QualifierCheck(Q_CONST);
+ TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_CONST;
+ break;
+ }
+ }
+ if (di->qual & Q_CONST)
+ CError_QualifierCheck(Q_CONST);
+ di->qual |= Q_CONST;
+ break;
+ case TK_VOLATILE:
+ if (di->thetype) {
+ if (di->thetype->type == TYPEPOINTER) {
+ if (TYPE_POINTER(di->thetype)->qual & Q_VOLATILE)
+ CError_QualifierCheck(Q_VOLATILE);
+ TYPE_POINTER(di->thetype)->qual |= Q_VOLATILE;
+ break;
+ } else if (di->thetype->type == TYPEMEMBERPOINTER) {
+ if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_VOLATILE)
+ CError_QualifierCheck(Q_VOLATILE);
+ TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_VOLATILE;
+ break;
+ }
+ }
+ if (di->qual & Q_VOLATILE)
+ CError_QualifierCheck(Q_VOLATILE);
+ di->qual |= Q_VOLATILE;
+ break;
+ case TK_PASCAL:
+ if (di->qual & Q_PASCAL)
+ CError_QualifierCheck(Q_PASCAL);
+ di->qual |= Q_PASCAL;
+ break;
+ case TK_EXPLICIT:
+ CError_QualifierCheck(di->qual & Q_EXPLICIT);
+ di->qual |= Q_EXPLICIT;
+ break;
+ case TK_VIRTUAL:
+ CError_QualifierCheck(di->qual & Q_VIRTUAL);
+ di->qual |= Q_VIRTUAL;
+ break;
+ case TK_IN:
+ CError_QualifierCheck(di->qual & Q_IN);
+ di->qual |= Q_IN;
+ break;
+ case TK_OUT:
+ CError_QualifierCheck(di->qual & Q_OUT);
+ di->qual |= Q_OUT;
+ break;
+ case TK_INOUT:
+ CError_QualifierCheck(di->qual & Q_INOUT);
+ di->qual |= Q_INOUT;
+ break;
+ case TK_BYCOPY:
+ CError_QualifierCheck(di->qual & Q_BYCOPY);
+ di->qual |= Q_BYCOPY;
+ break;
+ case TK_BYREF:
+ CError_QualifierCheck(di->qual & Q_BYREF);
+ di->qual |= Q_BYREF;
+ break;
+ case TK_ONEWAY:
+ CError_QualifierCheck(di->qual & Q_ONEWAY);
+ di->qual |= Q_ONEWAY;
+ break;
+ case TK_UU_DECLSPEC:
+ if ((tk = lex()) != '(')
+ CError_Error(114);
+ CParser_ParseDeclSpec(di, 0);
+ if ((tk = lex()) != ')')
+ CError_Error(115);
+ break;
+ case TK_ASM:
+ if (di->qual & Q_ASM)
+ CError_QualifierCheck(Q_ASM);
+ di->qual |= Q_ASM;
+ break;
+ case TK_INLINE:
+ if (di->qual & Q_INLINE)
+ CError_QualifierCheck(Q_INLINE);
+ di->qual |= Q_INLINE;
+ break;
+ case TK_SHORT:
+ if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE))
+ CError_Error(121);
+ typesize = 1;
+ break;
+ case TK_LONG:
+ if (copts.longlong) {
+ if (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)
+ CError_Error(121);
+ if (typesize) {
+ if (typesize != 2 || typetoken == TK_DOUBLE)
+ CError_Error(121);
+ typesize = 3;
+ } else {
+ typesize = 2;
+ }
+ } else {
+ if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE))
+ CError_Error(121);
+ typesize = 2;
+ }
+ break;
+ case TK_SIGNED:
+ if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR))
+ CError_Error(121);
+ signedness = -1;
+ break;
+ case TK_UNSIGNED:
+ if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR))
+ CError_Error(121);
+ signedness = 1;
+ break;
+ case TK_VOID:
+ if (typetoken || typesize || signedness)
+ CError_Error(121);
+ typetoken = TK_VOID;
+ break;
+ case TK_FLOAT:
+ if (typetoken || typesize || signedness)
+ CError_Error(121);
+ typetoken = TK_FLOAT;
+ break;
+ case TK_BOOL:
+ if (typetoken || typesize)
+ CError_Error(121);
+ typetoken = TK_BOOL;
+ break;
+ case TK_CHAR:
+ if (typetoken || typesize)
+ CError_Error(121);
+ typetoken = TK_CHAR;
+ break;
+ case TK_WCHAR_T:
+ if (typetoken || typesize || signedness)
+ CError_Error(121);
+ typetoken = TK_WCHAR_T;
+ break;
+ case TK_INT:
+ if (typetoken)
+ CError_Error(121);
+ typetoken = TK_INT;
+ break;
+ case TK_DOUBLE:
+ if (typetoken || signedness)
+ CError_Error(121);
+ typetoken = TK_DOUBLE;
+ break;
+ case TK_STRUCT:
+ if (typetoken || signedness || typesize)
+ CError_Error(121);
+ tk = lex();
+ scanstruct(di, STRUCT_TYPE_STRUCT);
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(di->thetype, NULL);
+ if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) {
+ typetoken = -1;
+ goto restart;
+ }
+ return;
+ case TK_CLASS:
+ if (typetoken || signedness || typesize)
+ CError_Error(121);
+ tk = lex();
+ CDecl_ParseClass(di, CLASS_MODE_2, 1, 0);
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(di->thetype, NULL);
+ if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) {
+ typetoken = -1;
+ goto restart;
+ }
+ return;
+ case TK_UNION:
+ if (typetoken || signedness || typesize)
+ CError_Error(121);
+ tk = lex();
+ scanstruct(di, STRUCT_TYPE_UNION);
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(di->thetype, NULL);
+ if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) {
+ typetoken = -1;
+ goto restart;
+ }
+ return;
+ case TK_ENUM:
+ if (typetoken || signedness || typesize)
+ CError_Error(121);
+ tk = lex();
+ scanenum(di);
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(di->thetype, NULL);
+ if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) {
+ typetoken = -1;
+ goto restart;
+ }
+ return;
+ case TK_TYPENAME:
+ if (typetoken || signedness || typesize || di->x53)
+ CError_Error(121);
+ di->x53 = 1;
+ tk = lex();
+ if (tk != TK_COLON_COLON && tk != TK_IDENTIFIER) {
+ CError_Error(121);
+ break;
+ }
+ goto some_shared_label;
+ case TK_COLON_COLON:
+ if (typetoken || signedness || typesize)
+ goto switchDefault;
+ goto some_shared_label;
+ case TK_UU_VECTOR:
+ if (typetoken || signedness || typesize)
+ CError_Error(121);
+ handle_vector:
+ if (CParser_GetVectorDeclSpec(&di->thetype)) {
+ if (tk == TK_CONST) {
+ if (di->qual == 0) {
+ di->qual |= Q_CONST;
+ tk = lex();
+ } else {
+ CError_Error(121);
+ }
+ }
+ if (tk == TK_VOLATILE) {
+ if (di->qual == 0) {
+ di->qual |= Q_VOLATILE;
+ tk = lex();
+ } else {
+ CError_Error(121);
+ }
+ }
+ return;
+ }
+ break;
+ case TK_UU_TYPEOF_UU:
+ if (typetoken || signedness || typesize)
+ CError_Error(121);
+ CParser_ParseTypeOf(di);
+ typetoken = -1;
+ goto bailOut;
+ case TK_IDENTIFIER:
+ if (copts.altivec_model && !typetoken && !signedness && !typesize && !strcmp(tkidentifier->name, "vector")) {
+ if (CParser_IsAltiVecPrefix())
+ goto handle_vector;
+ }
+ if (!typetoken && !signedness && !typesize) {
+ if (copts.objective_c && !strcmp(tkidentifier->name, "id")) {
+ di->thetype = CObjC_ParseID();
+ typetoken = -1;
+ goto bailOut;
+ }
+ some_shared_label:
+ CPrep_TokenStreamGetState(&state);
+ if (CScope_ParseDeclName(&pr)) {
+ if (pr.x8) {
+ if (IS_TYPE_TEMPLATE(pr.x8)) {
+ switch (TYPE_TEMPLATE(pr.x8)->dtype) {
+ case TEMPLDEP_ARGUMENT:
+ switch (TYPE_TEMPLATE(pr.x8)->u.pid.type) {
+ case TPT_TYPE:
+ break;
+ case TPT_NONTYPE:
+ CError_Error(348);
+ pr.x8 = TYPE(&stsignedint);
+ break;
+ case TPT_TEMPLATE:
+ CError_Error(230);
+ pr.x8 = TYPE(&stsignedint);
+ break;
+ default:
+#line 4109
+ CError_FATAL();
+ }
+ break;
+ case TEMPLDEP_QUALNAME:
+ if (!di->x53 && !pr.x20 && di->x55)
+ CError_Error(355);
+ break;
+ case TEMPLDEP_TEMPLATE:
+ case TEMPLDEP_ARRAY:
+ case TEMPLDEP_QUALTEMPL:
+ case TEMPLDEP_BITFIELD:
+ break;
+ default:
+#line 4136
+ CError_FATAL();
+ }
+ }
+
+ if (IS_TYPE_CLASS(pr.x8) && (TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100)) {
+ if (!CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.x8), 0)) {
+ if (di->x56) {
+ if (di->qual)
+ CError_Error(121);
+ di->thetype = pr.x8;
+ di->x57 = 1;
+ tk = lex();
+ return;
+ } else {
+ CError_Error(230);
+ pr.x8 = TYPE(&stsignedint);
+ }
+ }
+ }
+
+ TypedefDeclInfo(di, pr.x8, pr.xC);
+ di->x49 = pr.x20;
+ typetoken = -1;
+ tk = lex();
+ if (tk == '<' && copts.objective_c && IS_TYPE_CLASS(di->thetype) && TYPE_CLASS(di->thetype)->objcinfo)
+ di->thetype = CObjC_ParseTypeProtocol(di->thetype);
+ goto bailOut;
+ } else if (pr.nsol_14) {
+ if (pr.x1D) {
+ if (flag && (OBJECT(pr.nsol_14->object)->nspace == pr.nspace_0 || di->x4C)) {
+ di->x14 = pr.nsol_14;
+ if (IS_TYPE_FUNC(OBJECT(di->x14->object)->type) && ((TYPE_FUNC(OBJECT(di->x14->object)->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000))
+ r23 = 0;
+ } else {
+ CError_Error(121);
+ }
+ }
+ } else if (pr.obj_10) {
+ switch (pr.obj_10->otype) {
+ case OT_OBJECT:
+ if (pr.x1D) {
+ if (flag && (OBJECT(pr.obj_10)->nspace == pr.nspace_0 || di->x4C)) {
+ di->x10 = OBJECT(pr.obj_10);
+ if (IS_TYPE_FUNC(di->x10->type) && ((TYPE_FUNC(di->x10->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000))
+ r23 = 0;
+ } else {
+ CError_Error(121);
+ }
+ }
+ break;
+ case OT_ENUMCONST:
+ case OT_MEMBERVAR:
+ CError_Error(121);
+ break;
+ default:
+#line 4217
+ CError_FATAL();
+ }
+ } else if (pr.name_4) {
+ if (copts.cplusplus)
+ CError_Error(121);
+ } else if (pr.x21) {
+ CPrep_TokenStreamSetState(&state);
+ CPrep_UnLex();
+ tk = lex();
+ r23 = 0;
+ } else {
+#line 4234
+ CError_FATAL();
+ }
+ }
+ }
+ default:
+ switchDefault:
+ if (!typetoken && !signedness && !typesize) {
+ di->x4A = 1;
+ if (r23) {
+ if (!di->storageclass && !di->qual && !di->exportflags)
+ CError_Error(121);
+ else
+ CError_Warning(349);
+ }
+ }
+ if (typetoken >= 0)
+ di->thetype = getthetype(typetoken, typesize, signedness);
+ if (r24)
+ di->x48 = 1;
+ if (tk == TK_UU_ATTRIBUTE_UU)
+ CParser_ParseAttribute(NULL, di);
+ return;
+ case ';':
+ if (!typetoken && !signedness && !typesize && copts.warn_emptydecl)
+ CError_Warning(216);
+ if (typetoken >= 0)
+ di->thetype = getthetype(typetoken, typesize, signedness);
+ return;
+ }
+
+ tk = lex();
+bailOut:
+ r24 = 0;
+ goto restart;
+}
+
+void CParser_RegisterNonGlobalClass(TypeClass *tclass) {
+ struct ParentCleanup *p = lalloc(sizeof(struct ParentCleanup));
+ p->next = cparser_parentcleanup;
+ p->tclass = tclass;
+ cparser_parentcleanup = p;
+}
+
+void CParser_RegisterSingleExprFunction(Object *func, ENode *expr) {
+ struct SFuncList *p = lalloc(sizeof(struct SFuncList));
+ p->next = cparser_sfunclist;
+ p->func = func;
+ p->obj = NULL;
+ p->expr = expr;
+ cparser_sfunclist = p;
+}
+
+void CParser_RegisterDummyCtorFunction(Object *func, Object *obj) {
+ struct SFuncList *p = lalloc(sizeof(struct SFuncList));
+ p->next = cparser_sfunclist;
+ p->func = func;
+ p->obj = obj;
+ p->expr = NULL;
+ cparser_sfunclist = p;
+}
+
+static void CParser_FreeLocalHeap(void) {
+ struct SFuncList *s;
+ struct ParentCleanup *p;
+
+ while ((s = cparser_sfunclist)) {
+ cparser_sfunclist = s->next;
+ if (s->expr)
+ CFunc_GenerateSingleExprFunc(s->func, s->expr);
+ else
+ CFunc_GenerateDummyCtorFunc(s->func, s->obj);
+ }
+
+ if (cparser_parentcleanup) {
+ if (!CInline_CanFreeLHeap())
+ return;
+
+ for (p = cparser_parentcleanup; p; p = p->next) {
+ while (!p->tclass->nspace->parent->is_global)
+ p->tclass->nspace->parent = p->tclass->nspace->parent->parent;
+ }
+
+ cparser_parentcleanup = NULL;
+ }
+
+ freelheap();
+}
+
+static void CParser_GlobalCleanup(Boolean flag) {
+ Boolean working;
+
+ do {
+ CParser_FreeLocalHeap();
+ working = 0;
+
+ if (flag) {
+ if (cparser_classactions) {
+ CClass_ClassAction(cparser_classactions->tclass);
+ cparser_classactions = cparser_classactions->next;
+ working = 1;
+ } else if (CTempl_Instantiate()) {
+ working = 1;
+ }
+ }
+
+ while (CInline_GenerateDeferredFuncs()) {
+ CParser_FreeLocalHeap();
+ working = 1;
+ }
+ } while (working);
+}
+
+Boolean CParser_IsAnonymousUnion(DeclInfo *di, Boolean flag) {
+ return IS_TYPE_CLASS(di->thetype) &&
+ ((TYPE_CLASS(di->thetype)->mode == CLASS_MODE_1 || (flag && copts.cpp_extensions))) &&
+ IsTempName(TYPE_CLASS(di->thetype)->classname);
+}
+
+void CParser_CheckAnonymousUnion(DeclInfo *di, Boolean flag) {
+ ObjMemberVar *ivar;
+ Object *obj;
+ Object *ivar_obj;
+
+ if (!CParser_IsAnonymousUnion(di, 0)) {
+ if (copts.warn_emptydecl) {
+ switch (di->thetype->type) {
+ case TYPEENUM:
+ case TYPESTRUCT:
+ case TYPECLASS:
+ if (!di->storageclass && !di->qual)
+ return;
+ }
+ CError_Warning(216);
+ }
+ return;
+ }
+
+ if (!flag && di->storageclass != TK_STATIC)
+ CError_Error(177);
+
+ if (flag && di->storageclass != TK_STATIC) {
+ obj = CParser_NewLocalDataObject(di, 1);
+ obj->name = CParser_GetUniqueName();
+ CFunc_SetupLocalVarInfo(obj);
+ obj->u.var.info->noregister = 1;
+ } else {
+ obj = CParser_NewGlobalDataObject(di);
+ obj->name = CParser_GetUniqueName();
+ obj->nspace = cscope_root;
+ obj->sclass = TK_STATIC;
+ CInit_DeclareData(obj, NULL, NULL, obj->type->size);
+ }
+
+ for (ivar = TYPE_CLASS(di->thetype)->ivars; ivar; ivar = ivar->next) {
+ ivar_obj = galloc(sizeof(Object));
+ *ivar_obj = *obj;
+ ivar_obj->name = ivar->name;
+ ivar_obj->type = ivar->type;
+ ivar_obj->qual = ivar->qual;
+ ivar_obj->datatype = DALIAS;
+ ivar_obj->u.alias.object = obj;
+ ivar_obj->u.alias.offset = ivar->offset;
+ ivar_obj->u.alias.member = NULL;
+ CScope_AddObject(cscope_current, ivar_obj->name, OBJ_BASE(ivar_obj));
+ }
+}
+
+void CParser_NewCallBackAction(Object *obj, TypeClass *tclass) {
+ CallbackAction *act = galloc(sizeof(CallbackAction));
+ act->next = callbackactions;
+ act->obj = obj;
+ act->tclass = tclass;
+ callbackactions = act;
+ obj->flags |= OBJECT_FLAGS_8;
+}
+
+void CParser_NewClassAction(TypeClass *tclass) {
+ struct ClassAction *act = galloc(sizeof(struct ClassAction));
+ act->next = cparser_classactions;
+ act->tclass = tclass;
+ cparser_classactions = act;
+}
+
+void CParser_CallBackAction(Object *obj) {
+ CallbackAction *act;
+
+ for (act = callbackactions; act; act = act->next) {
+ if (act->obj == obj) {
+ CParser_NewClassAction(act->tclass);
+ return;
+ }
+ }
+
+#line 4551
+ CError_FATAL();
+}
+
+static Object *CParser_FindOverloadFunc(NameSpaceObjectList *list, TypeFunc *tfunc) {
+ while (list) {
+ if (list->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(list->object)->type))
+ if (CParser_CompareArgLists(tfunc->args, TYPE_FUNC(OBJECT(list->object)->type)->args) == 1)
+ return OBJECT(list->object);
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+Object *CParser_ParseObject(void) {
+ DeclInfo di;
+ CScopeParseResult pr;
+ NameSpaceObjectList *list;
+ Object *obj;
+
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&di, 1);
+ scandeclarator(&di);
+
+ if (di.name && (list = CScope_FindObjectList(&pr, di.name))) {
+ if (list->object->otype == OT_OBJECT) {
+ if (IS_TYPE_FUNC(di.thetype))
+ return CParser_FindOverloadFunc(list, TYPE_FUNC(di.thetype));
+
+ if (is_typesame(di.thetype, OBJECT(list->object)->type) && OBJECT(list->object)->qual == di.qual)
+ return OBJECT(list->object);
+
+ obj = OBJECT(list->object);
+ CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, di.thetype, di.qual);
+ }
+ }
+
+ return NULL;
+}
+
+void CParser_ParseGlobalDeclaration(void) {
+ DeclInfo di;
+
+ if (tk) {
+ CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL);
+ symdecloffset = cparser_fileoffset.tokenline;
+ symdecltoken = *CPrep_CurStreamElement();
+
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&di, 1);
+ if (di.storageclass == TK_REGISTER || di.storageclass == TK_AUTO) {
+ CError_Error(177);
+ di.storageclass = 0;
+ }
+
+ if (tk != ';')
+ scandeclaratorlist(&di);
+ else
+ CParser_CheckAnonymousUnion(&di, 0);
+
+ tk = lex();
+ } else {
+ CError_Error(102);
+ }
+}
+
+static void CParser_ParseLinkageSpecification(DeclInfo *di) {
+ UInt32 r29;
+ UInt8 r28;
+
+ if (!strcmp(tkstring, "C") || !strcmp(tkstring, "Objective C")) {
+ r29 = 0;
+ r28 = 1;
+ } else if (!strcmp(tkstring, "C++")) {
+ r29 = 0;
+ r28 = 0;
+ } else if (!strcmp(tkstring, "Pascal")) {
+ r29 = 8;
+ r28 = 1;
+ } else {
+ CError_Error(121);
+ r29 = 0;
+ r28 = 1;
+ }
+
+ if ((tk = lex()) == '{') {
+ while (1) {
+ if ((tk = lex()) == 0) {
+ CError_Error(130);
+ return;
+ }
+
+ if (tk == '}')
+ break;
+
+ CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL);
+ symdecloffset = cparser_fileoffset.tokenline;
+ symdecltoken = *CPrep_CurStreamElement();
+
+ memclrw(di, sizeof(DeclInfo));
+ di->x4E = r28;
+ di->qual = r29;
+ CParser_ParseDeclaration(di);
+ }
+ } else if (tk == TK_EXTERN && copts.cpp_extensions && lookahead() == TK_STRING) {
+ tk = lex();
+ CParser_ParseLinkageSpecification(di);
+ } else {
+ memclrw(di, sizeof(DeclInfo));
+ di->x4E = r28;
+ di->qual = r29;
+ CParser_GetDeclSpecs(di, 1);
+
+ if (di->storageclass != TK_TYPEDEF) {
+ if (di->storageclass && copts.pedantic)
+ CError_Warning(177);
+ if (!di->storageclass)
+ di->storageclass = TK_EXTERN;
+ }
+ if (copts.cpp_extensions)
+ di->x48 = 0;
+ if (tk != ';')
+ scandeclaratorlist(di);
+ }
+}
+
+static void CParser_ParseNameSpace(DeclInfo *di) {
+ NameSpace *nspace;
+ ObjNameSpace *objns;
+ HashNameNode *name;
+ Boolean flag;
+ CScopeSave save;
+ NameSpaceObjectList *list;
+ NameSpaceList *nsl;
+
+ if ((tk = lex()) == TK_IDENTIFIER) {
+ name = tkidentifier;
+ flag = 0;
+ if ((tk = lex()) == '=') {
+ CScope_ParseNameSpaceAlias(name);
+ return;
+ }
+ } else {
+ if (tk != '{') {
+ CError_Error(107);
+ return;
+ }
+ name = CParser_GetUnnamedNameSpaceName();
+ flag = 1;
+ }
+
+ nspace = cscope_current;
+ if (!(list = CScope_FindName(nspace, name))) {
+ objns = galloc(sizeof(ObjNameSpace));
+ memclrw(objns, sizeof(ObjNameSpace));
+ objns->otype = OT_NAMESPACE;
+ objns->access = ACCESSPUBLIC;
+ if (flag) {
+ nspace = CScope_NewListNameSpace(name, 1);
+ nspace->is_unnamed = 1;
+ nsl = galloc(sizeof(NameSpaceList));
+ nsl->next = cscope_current->usings;
+ nsl->nspace = nspace;
+ cscope_current->usings = nsl;
+ } else {
+ nspace = CScope_NewHashNameSpace(name);
+ if (cscope_current->is_unnamed)
+ nspace->is_unnamed = 1;
+ }
+
+ nspace->parent = cscope_current;
+ objns->nspace = nspace;
+ CScope_AddObject(cscope_current, name, OBJ_BASE(objns));
+ } else {
+ if (list->object->otype != OT_NAMESPACE)
+ CError_Error(320);
+ else
+ nspace = OBJ_NAMESPACE(list->object)->nspace;
+ }
+
+ if (tk != '{') {
+ CError_Error(135);
+ return;
+ }
+
+ CScope_SetNameSpaceScope(nspace, &save);
+ while (1) {
+ if ((tk = lex()) == 0) {
+ CError_Error(130);
+ break;
+ }
+
+ if (tk == '}')
+ break;
+
+ CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL);
+ symdecloffset = cparser_fileoffset.tokenline;
+ symdecltoken = *CPrep_CurStreamElement();
+
+ memclrw(di, sizeof(DeclInfo));
+ CParser_ParseDeclaration(di);
+ }
+ CScope_RestoreScope(&save);
+}
+
+static void CParser_ParseDeclaration(DeclInfo *di) {
+ switch (tk) {
+ case TK_AT_INTERFACE:
+ CObjC_ParseInterface();
+ break;
+ case TK_AT_IMPLEMENTATION:
+ CObjC_ParseImplementation();
+ break;
+ case TK_AT_PROTOCOL:
+ CObjC_ParseProtocol();
+ break;
+ case TK_AT_CLASS:
+ CObjC_ParseClassDeclaration();
+ break;
+ case TK_NAMESPACE:
+ CParser_ParseNameSpace(di);
+ break;
+ case TK_EXPORT:
+ CError_Error(190);
+ if ((tk = lex()) != TK_TEMPLATE) {
+ CError_Error(121);
+ return;
+ }
+ case TK_TEMPLATE:
+ CTempl_Parse(NULL, 0);
+ break;
+ case TK_USING:
+ if ((tk = lex()) == TK_NAMESPACE) {
+ tk = lex();
+ CScope_ParseUsingDirective(cscope_current);
+ } else {
+ CScope_ParseUsingDeclaration(cscope_current, 0, 0);
+ }
+ break;
+ case TK_EXTERN:
+ if (copts.cplusplus) {
+ di->storageclass = TK_EXTERN;
+ if ((tk = lex()) == TK_STRING) {
+ CParser_ParseLinkageSpecification(di);
+ break;
+ }
+ }
+ default:
+ CParser_GetDeclSpecs(di, 1);
+ if ((di->storageclass == TK_REGISTER || di->storageclass == TK_AUTO) != 0) {
+ CError_Error(177);
+ di->storageclass = 0;
+ }
+ if (tk != ';')
+ scandeclaratorlist(di);
+ else
+ CParser_CheckAnonymousUnion(di, 0);
+ CParser_GlobalCleanup(0);
+ }
+}
+
+void cparser(void) {
+ DeclInfo di;
+
+ if (copts.crippled && copts.optimizationlevel > 1) {
+ CError_Warning(385);
+ copts.optimizationlevel = 1;
+ CodeGen_UpdateOptimizerOptions();
+ CodeGen_UpdateBackEndOptions();
+ }
+
+ if ((tk = lex())) {
+ do {
+ CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL);
+ symdecloffset = cparser_fileoffset.tokenline;
+ symdecltoken = *CPrep_CurStreamElement();
+
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_ParseDeclaration(&di);
+ } while (tk && (tk = lex()));
+ } else {
+ if (!copts.cplusplus && copts.ANSI_strict)
+ CError_Error(102);
+ }
+
+ CInit_DefineTentativeData();
+ copts.defer_codegen = 0;
+ CParser_GlobalCleanup(1);
+
+ if (cparamblkptr->isPrecompiling != 1) {
+ CInline_Finish();
+ CParser_GlobalCleanup(1);
+ }
+
+ CClass_GenThunks();
+ if (cparamblkptr->isPrecompiling != 1)
+ CObjC_GenerateModule();
+
+ CSOM_Cleanup();
+ CInit_DefineTentativeData();
+}
diff --git a/compiler_and_linker/unsorted/CodeGen.c b/compiler_and_linker/unsorted/CodeGen.c
new file mode 100644
index 0000000..0867270
--- /dev/null
+++ b/compiler_and_linker/unsorted/CodeGen.c
@@ -0,0 +1,697 @@
+#include "compiler.h"
+#include "compiler/CError.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/tokens.h"
+#include "compiler/types.h"
+
+static Macro powcM;
+static Macro __powcM;
+static Macro ppc_cpu;
+static Macro profM;
+static Macro hostM;
+static Macro bendM;
+static Macro _ppc_M;
+static Macro longI;
+static Macro IEEED;
+Macro vecM;
+Macro altivecM;
+static Macro macM2;
+static Macro appleM;
+static Macro optM;
+static Macro alignM;
+static Macro _machM;
+static Macro archM;
+static Macro dynM;
+static Macro ppcM;
+Object *gFunction;
+static ObjectList *temps;
+PCodeLabel *returnlabel;
+PCodeLabel *cleanreturnlabel;
+Boolean needs_cleanup;
+Statement *current_statement;
+int has_catch_blocks;
+int disable_optimizer;
+SInt32 current_linenumber;
+Boolean has_altivec_arrays;
+short high_reg;
+short low_reg;
+short high_offset;
+short low_offset;
+short low_reg2;
+short high_reg2;
+PCodeLabel *pic_base_pcodelabel;
+Object *dyld_stub_binding_helper;
+Object *rt_cvt_fp2unsigned;
+Object *rt_profile_entry;
+Object *rt_profile_exit;
+Object *rt_div2i;
+Object *rt_div2u;
+Object *rt_mod2i;
+Object *rt_mod2u;
+Object *rt_shr2i;
+Object *rt_shr2u;
+Object *rt_shl2i;
+Object *rt_cvt_ull_dbl;
+Object *rt_cvt_sll_dbl;
+Object *rt_cvt_ull_flt;
+Object *rt_cvt_sll_flt;
+Object *rt_cvt_dbl_usll;
+static void *saveheaperror;
+
+enum {
+ GPRLimit = 10,
+ FPRLimit = 13,
+ VRLimit = 13
+};
+
+VarInfo *CodeGen_GetNewVarInfo(void) {
+ VarInfo *vi;
+
+ vi = lalloc(sizeof(VarInfo));
+ memclrw(vi, sizeof(VarInfo));
+
+ vi->deftoken = *CPrep_CurStreamElement();
+ vi->varnumber = localcount++;
+
+ return vi;
+}
+
+Object *maketemporary(Type *type) {
+ ObjectList *list;
+ Object *obj;
+
+ for (list = temps; list; list = list->next) {
+ obj = list->object;
+ if (obj->u.var.uid == 0 && obj->type == type) {
+ obj->u.var.uid = 1;
+ return obj;
+ }
+ }
+
+ obj = lalloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->access = ACCESSPUBLIC;
+ obj->datatype = DLOCAL;
+ obj->type = type;
+ obj->name = CParser_GetUniqueName();
+ obj->u.var.info = CodeGen_GetNewVarInfo();
+ obj->u.var.uid = 1;
+
+ list = lalloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->next = temps;
+ list->object = obj;
+ temps = list;
+
+ return obj;
+}
+
+static void free_temporaries(void) {
+ ObjectList *list;
+
+ for (list = temps; list; list = list->next)
+ list->object->u.var.uid = 0;
+}
+
+static void allocate_temporaries(void) {
+ ObjectList *list;
+
+ for (list = temps; list; list = list->next)
+ assign_local_memory(list->object);
+}
+
+void process_arguments(ArgumentProcessor func, Boolean flag) {
+ short gpr = 3;
+ short fpr = 1;
+ short vr = 2;
+ Type *type;
+ ObjectList *list;
+
+ for (list = arguments; list; list = list->next) {
+ type = list->object->type;
+ if (IS_TYPE_FLOAT(type)) {
+ func(list->object, (fpr <= FPRLimit) ? fpr : 0);
+ fpr++;
+ if (type->size == 4)
+ gpr++;
+ else
+ gpr += 2;
+ } else if (IS_TYPE_VECTOR(type)) {
+ func(list->object, (vr <= VRLimit) ? vr : 0);
+ vr++;
+ if (flag) {
+ if ((vr - 1) == 2)
+ gpr = 9;
+ else if ((vr - 1) > 2)
+ gpr = 11;
+ }
+ } else {
+ func(list->object, (gpr <= GPRLimit) ? gpr : 0);
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ if (type->size <= 4)
+ gpr += 1;
+ else
+ gpr += 2;
+ } else {
+ gpr += (type->size >> 2);
+ if (type->size & 3)
+ gpr++;
+ }
+ }
+ }
+
+ last_argument_register[RegClass_GPR] = gpr - 1;
+ last_argument_register[RegClass_FPR] = fpr - 1;
+ last_argument_register[RegClass_VR] = vr - 1;
+ if (flag)
+ move_varargs_to_memory();
+}
+
+static void retain_argument_register(Object *obj, short reg) {
+ VarInfo *vi = Registers_GetVarInfo(obj);
+ Type *type = obj->type;
+
+ if (reg && !vi->noregister && vi->used) {
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ if (type->size <= 4) {
+ retain_register(obj, RegClass_GPR, reg);
+ } else if (reg < GPRLimit) {
+ if (copts.little_endian)
+ retain_GPR_pair(obj, reg, reg + 1);
+ else
+ retain_GPR_pair(obj, reg + 1, reg);
+ }
+ } else if (IS_TYPE_FLOAT(type)) {
+ retain_register(obj, RegClass_FPR, reg);
+ } else if (IS_TYPE_VECTOR(type)) {
+ retain_register(obj, RegClass_VR, reg);
+ }
+ }
+}
+
+static void allocate_local_vregs(void) {
+ VarInfo *vi;
+ ObjectList *list;
+ Object *obj;
+
+ if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) {
+ if (assignable_registers[RegClass_GPR]) {
+ vi = pic_base.u.var.info;
+ vi->reg = 0;
+ assign_register_by_type(&pic_base);
+ pic_base_reg = vi->reg;
+#line 497
+ CError_ASSERT(pic_base_reg);
+ } else {
+#line 500
+ CError_FATAL();
+ }
+ } else {
+ pic_base_reg = 0;
+ }
+
+ for (list = exceptionlist; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+
+ set_last_exception_registers();
+
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ if (!IsTempName(obj->name)) {
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+ }
+
+ open_fe_temp_registers();
+
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ if (IsTempName(obj->name)) {
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+ }
+
+ for (list = toclist; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+
+ if (!vi->reg && vi->used && vi->usage > 1)
+ assign_register_by_type(obj);
+ }
+}
+
+static void allocate_local_GPRs(void) {
+ ObjectList *list;
+ Object *obj;
+ Object *winning_obj;
+ SInt32 winning_usage;
+ VarInfo *vi;
+ Type *type;
+
+ if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) {
+ vi = pic_base.u.var.info;
+ vi->reg = 0;
+ assign_register_by_type(&pic_base);
+ pic_base_reg = vi->reg;
+#line 605
+ CError_ASSERT(pic_base_reg);
+ } else {
+ pic_base_reg = 0;
+ }
+
+ while (assignable_registers[RegClass_GPR]) {
+ winning_obj = NULL;
+ winning_usage = -1;
+ if (!(disable_optimizer & 2)) {
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ type = obj->type;
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ if (!(disable_optimizer & 2)) {
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ type = obj->type;
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ for (list = toclist; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used) {
+ if (vi->usage >= winning_usage && vi->usage >= 3) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+
+ if (!winning_obj)
+ break;
+
+ assign_register_by_type(winning_obj);
+#line 698
+ CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2);
+ }
+}
+
+static void allocate_local_FPRs(void) {
+ ObjectList *list;
+ Object *obj;
+ Object *winning_obj;
+ SInt32 winning_usage;
+ VarInfo *vi;
+ Type *type;
+
+ while (assignable_registers[RegClass_FPR]) {
+ winning_obj = NULL;
+ winning_usage = -1;
+ if (!(disable_optimizer & 2)) {
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ type = obj->type;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_FLOAT(type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ if (!(disable_optimizer & 2)) {
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_FLOAT(obj->type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+
+ if (!winning_obj)
+ break;
+
+ assign_register_by_type(winning_obj);
+#line 782
+ CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2);
+ }
+}
+
+static void allocate_local_VRs(void) {
+ ObjectList *list;
+ Object *obj;
+ Object *winning_obj;
+ SInt32 winning_usage;
+ VarInfo *vi;
+
+ while (assignable_registers[RegClass_VR]) {
+ winning_obj = NULL;
+ winning_usage = -1;
+ if (!(disable_optimizer & 2)) {
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_VECTOR(obj->type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ if (!(disable_optimizer & 2)) {
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_VECTOR(obj->type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+
+ if (!winning_obj)
+ break;
+
+ assign_register_by_type(winning_obj);
+#line 846
+ CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2);
+ }
+}
+
+static void allocate_locals(void) {
+ has_altivec_arrays = 0;
+
+ if (!requires_frame && !optimizing)
+ process_arguments(retain_argument_register, 0);
+
+ if (optimizing) {
+ allocate_local_vregs();
+ } else {
+ allocate_local_GPRs();
+ allocate_local_FPRs();
+ allocate_local_VRs();
+ }
+
+ assign_locals_to_memory(locals);
+}
+
+void move_assigned_argument(Object *obj, short reg) {
+ VarInfo *vi;
+ Type *type;
+ SInt32 bytesLeft;
+ SInt32 offset;
+
+ vi = Registers_GetVarInfo(obj);
+ type = obj->type;
+#line 901
+ CError_ASSERT(obj->datatype == DLOCAL);
+
+ if (!vi->used)
+ return;
+
+ if (reg) {
+ if (vi->reg) {
+ if (TYPE_IS_8BYTES(type)) {
+ if (copts.little_endian) {
+ if (vi->reg != reg)
+ emitpcode(PC_MR, vi->reg, reg);
+ if (reg < GPRLimit) {
+#line 916
+ CError_FAIL((vi->regHi == reg) || (vi->reg == (reg + 1)));
+ if (vi->regHi != (reg + 1))
+ emitpcode(PC_MR, vi->regHi, reg + 1);
+ } else {
+ load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset);
+ }
+ } else {
+ if (vi->regHi != reg)
+ emitpcode(PC_MR, vi->regHi, reg);
+ if (reg < GPRLimit) {
+#line 931
+ CError_FAIL((vi->reg == reg) || (vi->regHi == (reg + 1)));
+ if (vi->reg != (reg + 1))
+ emitpcode(PC_MR, vi->reg, reg + 1);
+ } else {
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset);
+ }
+ }
+ } else if (vi->reg != reg) {
+ if (IS_TYPE_FLOAT(type)) {
+ emitpcode(PC_FMR, vi->reg, reg);
+ } else if (IS_TYPE_VECTOR(type)) {
+ emitpcode(PC_VMR, vi->reg, reg);
+ } else {
+ emitpcode(PC_MR, vi->reg, reg);
+ }
+ }
+ } else {
+ if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) {
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ load_store_register(PC_STB, reg, local_base_register(obj), obj, 0);
+ break;
+ case 2:
+ load_store_register(PC_STH, reg, local_base_register(obj), obj, 0);
+ break;
+ case 4:
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, 0);
+ break;
+ case 8:
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, 0);
+ if (reg < GPRLimit)
+ load_store_register(PC_STW, reg + 1, local_base_register(obj), obj, 4);
+ break;
+ default:
+#line 993
+ CError_FATAL();
+ }
+ } else if (IS_TYPE_FLOAT(type)) {
+ load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_VECTOR(type)) {
+ load_store_register(PC_STVX, reg, local_base_register(obj), obj, 0);
+ } else {
+ bytesLeft = (11 - reg) * 4;
+ if (bytesLeft > obj->type->size)
+ bytesLeft = obj->type->size;
+ offset = 0;
+ while (bytesLeft > 0) {
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, offset);
+ reg++;
+ offset += 4;
+ bytesLeft -= 4;
+ }
+ }
+ }
+ } else {
+ if (vi->reg) {
+ if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) {
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_FLOAT(type)) {
+ load_store_register((type->size == 4) ? PC_LFS : PC_LFD, vi->reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_VECTOR(type)) {
+ load_store_register(PC_LVX, vi->reg, local_base_register(obj), obj, 0);
+ } else {
+ switch (type->size) {
+ case 1:
+ load_store_register(PC_LBZ, vi->reg, local_base_register(obj), obj, 0);
+ break;
+ case 2:
+ load_store_register(is_unsigned(type) ? PC_LHZ : PC_LHA, vi->reg, local_base_register(obj), obj, 0);
+ break;
+ case 4:
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0);
+ break;
+ case 8:
+ load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset);
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset);
+ break;
+ default:
+#line 1095
+ CError_FATAL();
+ }
+ }
+ } else if (!optimizing) {
+ local_base_register(obj);
+ }
+ }
+}
+
+static void load_TOC_pointers(void) {
+ VarInfo *vi;
+ Object *obj;
+ ObjectList *list;
+ PCode *pc;
+
+ if (uses_globals && pic_base_reg) {
+ pic_base_pcodelabel = makepclabel();
+ pc = makepcode(PC_BC, 20, 7, 3);
+ pcsetlinkbit(pc);
+ pcsetsideeffects(pc);
+ appendpcode(pclastblock, pc);
+ pcbranch(pclastblock, pic_base_pcodelabel);
+ makepcblock();
+ pclabel(pclastblock, pic_base_pcodelabel);
+ emitpcode(PC_MFLR, pic_base_reg);
+ }
+
+ // TODO: depends on Operands
+ for (list = toclist; list; list = list->next) {
+
+ }
+}
+
+static Boolean has_vararglist(Object *funcobj) {
+ FuncArg *arg;
+
+ arg = TYPE_FUNC(funcobj->type)->args;
+ while (arg && arg != &elipsis)
+ arg = arg->next;
+
+ return arg == &elipsis;
+}
+
+void assign_labels() {
+ // TODO
+}
+
+static Boolean islaststatement(Statement *stmt) {
+ for (stmt = stmt->next; stmt; stmt = stmt->next) {
+ if (stmt->type > ST_LABEL)
+ return 0;
+ }
+ return 1;
+}
+
+static void newstatement(SInt32 sourceoffset, UInt16 value, int flag) {
+ PCodeBlock *block = pclastblock;
+
+ pcloopweight = value;
+ if (!block->pcodeCount)
+ block->loopWeight = value;
+
+ if (block->pcodeCount > 100)
+ branch_label(makepclabel());
+
+ if (flag)
+ block->flags |= fPCBlockFlag4000;
+}
+
+static void expressionstatement(ENode *expr) {
+}
+
+static void labelstatement() {}
+static void gotostatement() {}
+static void gotoexpression() {}
+static void conditionalstatement() {}
+static void returnstatement() {}
+static void capturestackpointer() {}
+static void resetstackpointer() {}
+static void callprofiler() {}
+static void exitprofiler() {}
+void CodeGen_Generator() {}
+void CodeGen_GenVDispatchThunk() {}
+void CodeGen_SetupRuntimeObjects() {}
+Boolean CodeGen_ReInitRuntimeObjects(Boolean is_precompiler) {}
+Boolean CodeGen_IsPublicRuntimeObject(Object *obj) {}
+void CodeGen_SOMStub() {}
+void CodeGen_ParseDeclSpec() {}
+static void CodeGen_EOLCheck() {}
+static void schedule_for() {}
+static void pragma_scheduling() {}
+static void CodeGen_ParseLongIntegerORonORoff() {}
+void CodeGen_ParsePragma(HashNameNode *name) {}
+void CodeGen_UpdateObject(Object *object) {}
+void CodeGen_UpdateBackEndOptions() {}
+void CodeGen_objc_method_self_offset() {}
+void CodeGen_objc_method_sel_offset() {}
+void CodeGen_objc_method_arg_offset() {}
+void CodeGen_objc_method_args_size() {}
+void CodeGen_HandleIntrinsicCall() {}
+void CodeGen_HandleTypeCast() {}
+void CodeGen_AssignCheck() {}
+void CodeGen_CollapseVectorExpression() {}
+void CodeGen_InsertSpecialMacros() {}
+char *CodeGen_ExpandSpecialMacro(Macro *macro) {}
+void CodeGen_reportheapinfo() {}
+static void CodeGen_heaperror() {}
+void CodeGen_InitialSanityCheck() {}
diff --git a/compiler_and_linker/unsorted/Operands.c b/compiler_and_linker/unsorted/Operands.c
new file mode 100644
index 0000000..c0fee65
--- /dev/null
+++ b/compiler_and_linker/unsorted/Operands.c
@@ -0,0 +1,1044 @@
+#include "compiler/Operands.h"
+#include "compiler/CError.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler.h"
+
+unsigned long long uns_to_float_cc = 0x4330000000000000;
+unsigned long long int_to_float_cc = 0x4330000080000000;
+Float one_point_zero = {1.0};
+
+void load_immediate(short reg, SInt32 value) {
+ short tmpreg = reg;
+ short tmpreg2;
+
+ if (!FITS_IN_SHORT(value)) {
+ if (copts.optimizationlevel > 1 && value)
+ tmpreg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmpreg2 = tmpreg, 0, (short) HIGH_PART(value));
+ if (value)
+ emitpcode(PC_ADDI, reg, tmpreg2, 0, LOW_PART(value));
+ } else {
+ emitpcode(PC_LI, reg, value);
+ }
+}
+
+static void set_op_flags(Operand *op, ENode *expr) {
+#line 118
+ CError_ASSERT(op);
+
+ if (expr) {
+ if (expr->type == EINTCONST) {
+ op->flags = 0;
+ if (expr->flags & ENODE_FLAG_VOLATILE)
+ op->flags |= OpndFlags_Volatile;
+ if (expr->flags & ENODE_FLAG_CONST)
+ op->flags |= OpndFlags_Const;
+ } else {
+ op->flags = CParserIsVolatileExpr(expr) ? OpndFlags_Volatile : 0;
+ op->flags |= CParserIsConstExpr(expr) ? OpndFlags_Const : 0;
+ }
+ } else {
+ op->flags = 0;
+ }
+}
+
+void symbol_operand(Operand *op, Object *obj) {
+ memclrw(op, sizeof(Operand));
+ op->optype = OpndType_Symbol;
+ op->object = obj;
+}
+
+void indirect(Operand *op, ENode *expr) {
+ switch (op->optype) {
+ case OpndType_GPRPair:
+#line 163
+ CError_FATAL();
+ case OpndType_CRField:
+ case OpndType_IndirectGPR_ImmOffset:
+ case OpndType_IndirectGPR_Indexed:
+ case OpndType_IndirectSymbol:
+ if (op->optype)
+ Coerce_to_register(op, (Type *) &void_ptr, 0);
+ case OpndType_GPR:
+ op->immOffset = 0;
+ op->object = NULL;
+ case OpndType_GPR_ImmOffset:
+ op->optype = OpndType_IndirectGPR_ImmOffset;
+ set_op_flags(op, expr);
+ break;
+ case OpndType_GPR_Indexed:
+ op->optype = OpndType_IndirectGPR_Indexed;
+ set_op_flags(op, expr);
+ break;
+ case OpndType_Absolute:
+ if (FITS_IN_SHORT(op->abs_address)) {
+ op->reg = 0;
+ op->immOffset = op->abs_address;
+ } else {
+ emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(op->abs_address));
+ op->immOffset = LOW_PART(op->abs_address);
+ }
+ op->object = NULL;
+ op->optype = OpndType_IndirectGPR_ImmOffset;
+ set_op_flags(op, expr);
+ break;
+ case OpndType_Symbol:
+ op->optype = OpndType_IndirectSymbol;
+ set_op_flags(op, expr);
+ break;
+ default:
+#line 215
+ CError_FATAL();
+ }
+}
+
+#define COMBO_OP(a, b) (b + (a * 11))
+
+void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) {
+ Operand *tmp_op;
+ int tmp;
+
+ if (opA->optype == OpndType_Symbol || opA->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(opA);
+ if (opB->optype == OpndType_Symbol || opB->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(opB);
+
+ switch (COMBO_OP(opA->optype, opB->optype)) {
+ case COMBO_OP(OpndType_GPR, OpndType_GPR):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opA->reg;
+ opOut->regOffset = opB->reg;
+ break;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_ImmOffset):
+ if (FITS_IN_SHORT(opA->immOffset + opB->immOffset) && (!opA->object || !opB->object)) {
+ opB->immOffset += opA->immOffset;
+ if (!opB->object)
+ opB->object = opA->object;
+ } else {
+ tmp = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ add_immediate(tmp, opA->reg, opA->object, opA->immOffset);
+ opA->reg = tmp;
+ }
+ case COMBO_OP(OpndType_GPR, OpndType_GPR_ImmOffset):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR):
+ if (opA->reg == _FP_ || opA->reg == _CALLER_SP_) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = opB->reg;
+ add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset));
+ } else if (opB->reg == _FP_ || opB->reg == _CALLER_SP_) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = opA->reg;
+ add_immediate(opOut->reg, opB->reg, opA->object, LOW_PART(opA->immOffset));
+ } else if (opA->object) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = opB->reg;
+ add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset));
+ } else {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->immOffset = opA->immOffset;
+ opOut->object = opA->object;
+ emitpcode(PC_ADD, opOut->reg, opA->reg, opB->reg);
+ }
+ break;
+ case COMBO_OP(OpndType_GPR, OpndType_GPR_Indexed):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opA->reg;
+ opOut->regOffset = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->regOffset, opA->regOffset, opB->reg);
+ break;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_Indexed):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_ImmOffset):
+ if (opB->object) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg
+ : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset);
+ add_immediate(opOut->regOffset, opB->reg, opB->object, opB->immOffset);
+ } else {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->immOffset = opB->immOffset;
+ opOut->object = opB->object;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg
+ : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset);
+ emitpcode(PC_ADD, opOut->reg, opOut->reg, opB->reg);
+ }
+ break;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_Indexed):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opA->reg;
+ opOut->regOffset = (output_reg && (output_reg != opA->regOffset)) ? output_reg
+ : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->regOffset, opB->reg, opB->regOffset);
+ emitpcode(PC_ADD, opOut->regOffset, opOut->regOffset, opA->regOffset);
+ break;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_Absolute):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_Absolute, OpndType_GPR_ImmOffset):
+ if (!opB->object) {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->reg = opB->reg;
+ opOut->immOffset = opB->immOffset;
+ opOut->object = opB->object;
+ if (FITS_IN_SHORT(opOut->immOffset + opA->abs_address)) {
+ opOut->immOffset += opA->abs_address;
+ } else {
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ if (!HIGH_PART(opA->abs_address)) {
+ emitpcode(PC_ADDI, opOut->reg, opB->reg, 0, LOW_PART(opA->abs_address));
+ } else {
+ emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->abs_address));
+ if (FITS_IN_SHORT(opOut->immOffset + LOW_PART(opA->abs_address))) {
+ opOut->immOffset += LOW_PART(opA->abs_address);
+ } else {
+ emitpcode(PC_ADDI, opOut->reg, opOut->reg, 0, LOW_PART(opA->abs_address));
+ }
+ }
+ }
+ break;
+ } else if (opB->object->datatype == DLOCAL && can_add_displ_to_local(opB->object, opB->immOffset + opA->abs_address)) {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->object = opB->object;
+ opOut->reg = opB->reg;
+ opOut->immOffset = LOW_PART(opB->immOffset + opA->abs_address);
+ break;
+ } else {
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ add_immediate(opOut->reg, opB->reg, opB->object, opB->immOffset);
+ opB->optype = OpndType_GPR;
+ opB->reg = opOut->reg;
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ }
+ case COMBO_OP(OpndType_GPR, OpndType_Absolute):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_Absolute, OpndType_GPR):
+ opOut->optype = (opA->abs_address != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR;
+ opOut->immOffset = LOW_PART(opA->abs_address);
+ opOut->object = NULL;
+ if (FITS_IN_SHORT(opA->abs_address)) {
+ opOut->reg = opB->reg;
+ } else {
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->abs_address));
+ }
+ break;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_Absolute):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_Absolute, OpndType_GPR_Indexed):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opB->reg;
+ opOut->regOffset = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ if (!HIGH_PART(opA->abs_address)) {
+ emitpcode(PC_ADDI, opOut->regOffset, opB->regOffset, 0, LOW_PART(opA->abs_address));
+ } else {
+ emitpcode(PC_ADDIS, opOut->regOffset, opB->regOffset, 0, (short) HIGH_PART(opA->abs_address));
+ if (opA->abs_address != 0)
+ emitpcode(PC_ADDI, opOut->regOffset, opOut->regOffset, 0, LOW_PART(opA->abs_address));
+ }
+ break;
+ case COMBO_OP(OpndType_Absolute, OpndType_Absolute):
+ opOut->optype = OpndType_Absolute;
+ opOut->abs_address = opA->abs_address + opB->abs_address;
+ break;
+ default:
+#line 415
+ CError_FATAL();
+ }
+}
+
+void coerce_to_addressable(Operand *op) {
+ UInt32 offset;
+ short reg;
+ short flag;
+ short tmp;
+ Object *obj;
+
+ flag = 0;
+ obj = op->object;
+ tmp = 0;
+
+ switch (op->optype) {
+ case OpndType_GPR:
+ case OpndType_GPR_ImmOffset:
+ case OpndType_GPR_Indexed:
+ case OpndType_GPRPair:
+ case OpndType_Absolute:
+ case OpndType_VR:
+ case OpndType_CRField:
+ case OpndType_IndirectGPR_ImmOffset:
+ case OpndType_IndirectGPR_Indexed:
+ break;
+ case OpndType_IndirectSymbol:
+ flag = 1;
+ case OpndType_Symbol:
+ if (obj->datatype == DLOCAL) {
+ if (!local_is_16bit_offset(obj)) {
+ reg = used_virtual_registers[RegClass_GPR]++;
+ op_absolute_ha(reg, local_base_register(obj), obj, 0, 1);
+ op->optype = OpndType_GPR_ImmOffset;
+ op->reg = reg;
+ op->object = obj;
+ } else {
+ op->optype = OpndType_GPR_ImmOffset;
+ op->reg = local_base_register(obj);
+ op->object = obj;
+ }
+ } else if (obj->datatype == DABSOLUTE) {
+ offset = obj->u.address;
+ if (FITS_IN_SHORT(offset)) {
+ op->reg = 0;
+ op->immOffset = obj->u.address;
+ } else {
+ emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(offset));
+ op->immOffset = LOW_PART(obj->u.address);
+ }
+ op->object = obj;
+ op->optype = OpndType_GPR_ImmOffset;
+ } else {
+ if (copts.codegen_pic)
+ tmp = pic_base_reg;
+ reg = used_virtual_registers[RegClass_GPR]++;
+ op_absolute_ha(reg, tmp, obj, 0, 1);
+ op->optype = OpndType_GPR_ImmOffset;
+ op->reg = reg;
+ }
+ if (flag) {
+ if (op->optype == OpndType_GPR_ImmOffset) {
+ op->optype = OpndType_IndirectGPR_ImmOffset;
+ } else {
+#line 563
+ CError_FATAL();
+ }
+ }
+ break;
+ default:
+#line 581
+ CError_FATAL();
+ }
+}
+
+void Coerce_to_register(Operand *op, Type *type, short output_reg) {
+ SInt32 offset;
+ short opcode;
+ short reg;
+ short tmp;
+ short cond_neg;
+ short cond;
+ short bit_offset;
+ short bit_size;
+
+ if (TYPE_IS_8BYTES(type)) {
+ coerce_to_register_pair(op, type, output_reg, 0);
+ return;
+ }
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_GPRPair:
+ return;
+ case OpndType_GPR:
+ return;
+ case OpndType_GPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ add_immediate(reg, op->reg, op->object, op->immOffset);
+ break;
+ case OpndType_GPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, reg, op->reg, op->regOffset);
+ break;
+ case OpndType_Absolute:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ offset = op->abs_address;
+ if (FITS_IN_SHORT(offset)) {
+ emitpcode(PC_LI, reg, offset);
+ } else {
+ tmp = reg;
+ if (copts.optimizationlevel > 1 && offset)
+ tmp = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmp, 0, (short) HIGH_PART(offset));
+ if (offset)
+ emitpcode(PC_ADDI, reg, tmp, 0, LOW_PART(offset));
+ }
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opcode = PC_LWZ;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_LBZ;
+ break;
+ case 2:
+ if (is_unsigned(type))
+ opcode = PC_LHZ;
+ else
+ opcode = PC_LHA;
+ break;
+ }
+ } else {
+#line 680
+ CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ load_store_register(opcode, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opcode = PC_LWZX;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_LBZX;
+ break;
+ case 2:
+ if (is_unsigned(type))
+ opcode = PC_LHZX;
+ else
+ opcode = PC_LHAX;
+ break;
+ }
+ } else {
+#line 724
+ CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ emitpcode(opcode, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_CRField:
+ cond_neg = 0;
+ cond = 0;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MFCR, tmp = reg);
+ switch (op->regOffset) {
+ case ENOTEQU:
+ cond_neg = 1;
+ case EEQU:
+ cond = 2;
+ break;
+ case EGREATEREQU:
+ cond_neg = 1;
+ case ELESS:
+ cond = 0;
+ break;
+ case ELESSEQU:
+ cond_neg = 1;
+ case EGREATER:
+ cond = 1;
+ break;
+ default:
+#line 758
+ CError_FATAL();
+ }
+ bit_offset = cond + (op->reg << 2);
+ bit_size = 1;
+ emitpcode(PC_RLWINM, tmp, tmp, (bit_size + bit_offset) & 31, 32 - bit_size, 31);
+ if (cond_neg)
+ emitpcode(PC_XORI, tmp, tmp, 1);
+ break;
+ default:
+#line 769
+ CError_FATAL();
+ }
+
+ op->optype = OpndType_GPR;
+ op->reg = reg;
+}
+
+void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short output_regHi) {
+ SInt32 offset;
+ short reg;
+ short regHi;
+ short tmp1;
+ short tmp2;
+
+ regHi = -1;
+
+#line 794
+ CError_ASSERT(TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8));
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_GPRPair:
+ if (output_reg && !output_regHi)
+ output_regHi = used_virtual_registers[RegClass_GPR]++;
+ if (output_regHi && !output_reg)
+ output_reg = used_virtual_registers[RegClass_GPR]++;
+ if (op->reg != output_reg || op->regHi != output_regHi) {
+ tmp1 = output_reg ? output_reg : op->reg;
+ tmp2 = output_regHi ? output_regHi : op->regHi;
+ if (tmp1 != op->reg) {
+ if (tmp1 == op->regHi) {
+#line 818
+ CError_ASSERT(tmp1 != tmp2);
+ emitpcode(PC_MR, tmp2, op->regHi);
+ emitpcode(PC_MR, tmp1, op->reg);
+ } else {
+ emitpcode(PC_MR, tmp1, op->reg);
+ if (op->regHi != tmp2)
+ emitpcode(PC_MR, tmp2, op->regHi);
+ }
+ } else if (tmp2 != op->regHi) {
+ if (tmp2 == op->reg) {
+#line 832
+ CError_ASSERT(tmp1 != tmp2);
+ emitpcode(PC_MR, tmp1, op->reg);
+ emitpcode(PC_MR, tmp2, op->regHi);
+ } else {
+ emitpcode(PC_MR, tmp2, op->regHi);
+ if (op->reg != tmp1)
+ emitpcode(PC_MR, tmp1, op->reg);
+ }
+ }
+ }
+ reg = op->reg;
+ regHi = op->regHi;
+ break;
+ case OpndType_GPR:
+#line 849
+ CError_FATAL();
+ break;
+ case OpndType_GPR_ImmOffset:
+#line 852
+ CError_FATAL();
+ break;
+ case OpndType_GPR_Indexed:
+#line 855
+ CError_FATAL();
+ break;
+ case OpndType_Absolute:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ offset = op->abs_address;
+ if (FITS_IN_SHORT(offset)) {
+ emitpcode(PC_LI, reg, offset);
+ } else {
+ tmp1 = reg;
+ if (copts.optimizationlevel > 1 && offset)
+ tmp1 = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmp1, 0, (short) HIGH_PART(offset));
+ if (offset)
+ emitpcode(PC_ADDI, reg, tmp1, 0, LOW_PART(offset));
+ }
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ if (is_unsigned(type) || offset >= 0)
+ load_immediate(regHi, 0);
+ else
+ load_immediate(regHi, -1);
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ if (op->reg == regHi) {
+ if (op->reg == reg) {
+#line 887
+ CError_FATAL();
+ } else {
+ load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset);
+ setpcodeflags(op->flags);
+ }
+ } else {
+ load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset);
+ setpcodeflags(op->flags);
+ }
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, reg, op->reg, op->regOffset);
+ load_store_register(PC_LWZ, regHi, reg, NULL, high_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_LWZ, reg, reg, NULL, low_offset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+#line 912
+ CError_FATAL();
+ }
+
+ if (regHi == -1) {
+#line 916
+ CError_FATAL();
+ } else {
+ op->optype = OpndType_GPRPair;
+ op->reg = reg;
+ op->regHi = regHi;
+ }
+}
+
+void Coerce_to_fp_register(Operand *op, TypeIntegral *tint, short output_reg) {
+ short reg;
+
+ coerce_to_addressable(op);
+
+ switch (op->optype) {
+ case OpndType_FPR:
+ reg = op->reg;
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ load_store_register((tint->size == 4) ? PC_LFS : PC_LFD, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ emitpcode((tint->size == 4) ? PC_LFSX : PC_LFDX, reg, op->reg, op->regOffset, 0, 0x390);
+ setpcodeflags(op->flags);
+ break;
+ default:
+#line 986
+ CError_FATAL();
+ }
+
+ op->optype = OpndType_FPR;
+ op->reg = reg;
+}
+
+void Coerce_to_v_register(Operand *op, TypeStruct *tstruct, short output_reg) {
+ short reg;
+
+ coerce_to_addressable(op);
+
+ switch (op->optype) {
+ case OpndType_VR:
+ reg = op->reg;
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
+ load_store_register(PC_LVX, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
+ emitpcode(PC_LVX, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_Absolute:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
+ switch (tstruct->stype) {
+ case STRUCT_TYPE_4:
+ case STRUCT_TYPE_5:
+ case STRUCT_TYPE_6:
+ emitpcode(PC_VSPLTISB, reg, op->abs_address);
+ break;
+ case STRUCT_TYPE_7:
+ case STRUCT_TYPE_8:
+ case STRUCT_TYPE_9:
+ case STRUCT_TYPE_E:
+ emitpcode(PC_VSPLTISH, reg, op->abs_address);
+ break;
+ case STRUCT_TYPE_A:
+ case STRUCT_TYPE_B:
+ case STRUCT_TYPE_C:
+ case STRUCT_TYPE_D:
+ emitpcode(PC_VSPLTISW, reg, op->abs_address);
+ break;
+ default:
+#line 1049
+ CError_FATAL();
+ }
+ op->optype = OpndType_VR;
+ op->reg = reg;
+ setpcodeflags(op->flags);
+ break;
+ default:
+#line 1059
+ CError_FATAL();
+ }
+
+ op->optype = OpndType_VR;
+ op->reg = reg;
+}
+
+void store(short reg, Operand *op, Type *type) {
+ short opcode;
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ opcode = PC_STW;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_STB;
+ break;
+ case 2:
+ opcode = PC_STH;
+ break;
+ }
+ } else {
+#line 1171
+ CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ load_store_register(opcode, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ opcode = PC_STWX;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_STBX;
+ break;
+ case 2:
+ opcode = PC_STHX;
+ break;
+ }
+ } else {
+#line 1188
+ CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ emitpcode(opcode, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+#line 1193
+ CError_FATAL();
+ }
+}
+
+void store_pair(short reg, short regHi, Operand *op, Type *type) {
+ short tmp;
+
+#line 1208
+ CError_ASSERT(TYPE_IS_8BYTES(type));
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ load_store_register(PC_STW, reg, op->reg, op->object, op->immOffset + low_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_STW, regHi, op->reg, op->object, op->immOffset + high_offset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ tmp = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, tmp, op->reg, op->regOffset);
+ load_store_register(PC_STW, reg, tmp, NULL, low_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_STW, regHi, tmp, NULL, high_offset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+#line 1228
+ CError_FATAL();
+ }
+}
+
+void store_fp(short reg, Operand *op, TypeIntegral *tint) {
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ load_store_register((tint->size == 4) ? PC_STFS : PC_STFD, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ emitpcode((tint->size == 4) ? PC_STFSX : PC_STFDX, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+#line 1259
+ CError_FATAL();
+ }
+}
+
+void store_v(short reg, Operand *op, TypeStruct *tstruct) {
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ load_store_register(PC_STVX, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ emitpcode(PC_STVX, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+#line 1283
+ CError_FATAL();
+ }
+}
+
+static Boolean last_matches_rlwinm_or_exts(Operand *op, short opcode, short b, short c) {
+ PCode *pc;
+
+ if (pclastblock->pcodeCount <= 0)
+ return 0;
+
+ pc = pclastblock->lastPCode;
+ if (pc->args[0].kind != PCOp_REGISTER || pc->args[0].arg != RegClass_GPR || pc->args[0].data.reg.reg != op->reg)
+ return 0;
+
+ if (pc->op != opcode && (opcode != PC_EXTSH || pc->op != PC_EXTSB))
+ return 0;
+
+ if (opcode == PC_RLWINM) {
+ if (pc->args[2].data.imm.value != 0 || pc->args[3].data.imm.value != b || pc->args[4].data.imm.value != c)
+ return 0;
+ }
+
+ return 1;
+}
+
+void extend32(Operand *op, Type *type, short output_reg) {
+ int r28;
+ int reg;
+
+ r28 = op->optype >= OpndType_IndirectGPR_ImmOffset;
+ if (op->optype != OpndType_GPR)
+ Coerce_to_register(op, type, output_reg);
+
+ switch (type->size) {
+ case 1:
+ if (is_unsigned(type)) {
+ if (r28)
+ return;
+ if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 24, 31))
+ return;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, reg, op->reg, 0, 24, 31);
+ } else {
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ if (last_matches_rlwinm_or_exts(op, PC_EXTSB, 0, 0))
+ return;
+ emitpcode(PC_EXTSB, reg, op->reg);
+ }
+ break;
+ case 2:
+ if (r28)
+ return;
+ if (is_unsigned(type)) {
+ if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 16, 31))
+ return;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, reg, op->reg, 0, 16, 31);
+ } else {
+ if (last_matches_rlwinm_or_exts(op, PC_EXTSH, 0, 0))
+ return;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_EXTSH, reg, op->reg);
+ }
+ break;
+ default:
+#line 1389
+ CError_FATAL();
+ }
+
+ op->optype = OpndType_GPR;
+ op->reg = reg;
+}
+
+void extend64(Operand *op, Type *type, short output_reg, short output_regHi) {
+ short tmp;
+ short regHi;
+
+ if (op->optype != OpndType_GPR)
+ Coerce_to_register(op, type, output_reg);
+
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ if (regHi == op->reg) {
+ tmp = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MR, tmp, op->reg);
+ op->reg = tmp;
+ }
+
+ if (is_unsigned(type))
+ load_immediate(regHi, 0);
+ else
+ emitpcode(PC_SRAWI, regHi, op->reg, 31);
+
+ op->optype = OpndType_GPRPair;
+ op->regHi = regHi;
+}
+
+void load_floating_constant(short reg, TypeIntegral *type, double *data) {
+ // do me AFTER
+}
+
+void convert_integer_to_floating(Operand *op, Boolean is_single, short output_reg) {
+ // issue with matching the PC_FSUB/PC_FSUBS ternary
+ Operand temp_op;
+ double d;
+ int const_reg;
+ int tmp_reg;
+ int work_reg;
+ int result_reg;
+ short opcode;
+
+ symbol_operand(&temp_op, maketemporary((Type *) &stdouble));
+ coerce_to_addressable(&temp_op);
+ d = *((double *) &int_to_float_cc);
+
+ const_reg = used_virtual_registers[RegClass_FPR]++;
+ load_floating_constant(const_reg, &stdouble, &d);
+
+ tmp_reg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_XORIS, tmp_reg, op->reg, 0x8000);
+ load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, low_offset);
+
+ emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330);
+ load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset);
+
+ load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0);
+
+ result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ //opcode = PC_FSUB;
+ //if (is_single)
+ // opcode = PC_FSUBS;
+ //opcode = (is_single != 0) ? PC_FSUBS : PC_FSUB;
+ if (is_single != 0)
+ opcode = PC_FSUBS;
+ else
+ opcode = PC_FSUB;
+ emitpcode(opcode, result_reg, work_reg, const_reg);
+
+ op->optype = OpndType_FPR;
+ op->reg = result_reg;
+}
+
+void convert_unsigned_to_floating(Operand *op, Boolean is_single, short output_reg) {
+ // issue with matching the PC_FSUB/PC_FSUBS ternary
+ Operand temp_op;
+ double d;
+ int const_reg;
+ int tmp_reg;
+ int work_reg;
+ int result_reg;
+ short opcode;
+
+ symbol_operand(&temp_op, maketemporary((Type *) &stdouble));
+ coerce_to_addressable(&temp_op);
+ d = *((double *) &uns_to_float_cc);
+
+ const_reg = used_virtual_registers[RegClass_FPR]++;
+ load_floating_constant(const_reg, &stdouble, &d);
+
+ load_store_register(PC_STW, op->reg, temp_op.reg, temp_op.object, low_offset);
+
+ emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330);
+ load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset);
+
+ load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0);
+
+ result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ //opcode = PC_FSUB;
+ //if (is_single)
+ // opcode = PC_FSUBS;
+ //opcode = (is_single != 0) ? PC_FSUBS : PC_FSUB;
+ if (is_single != 0)
+ opcode = PC_FSUBS;
+ else
+ opcode = PC_FSUB;
+ emitpcode(opcode, result_reg, work_reg, const_reg);
+
+ op->optype = OpndType_FPR;
+ op->reg = result_reg;
+}
+
+void convert_floating_to_integer(Operand *op, short output_reg) {
+ Operand temp_op;
+ int tmp_reg;
+ int result_reg;
+
+ symbol_operand(&temp_op, maketemporary((Type *) &stdouble));
+ coerce_to_addressable(&temp_op);
+
+ tmp_reg = used_virtual_registers[RegClass_FPR]++;
+ emitpcode(PC_FCTIWZ, tmp_reg, op->reg);
+ load_store_register(PC_STFD, tmp_reg, temp_op.reg, temp_op.object, 0);
+
+ result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ load_store_register(PC_LWZ, result_reg, temp_op.reg, temp_op.object, low_offset);
+
+ op->optype = OpndType_GPR;
+ op->reg = result_reg;
+}
+
+void convert_floating_to_unsigned(Operand *op, short output_reg) {
+ static UInt32 used_regs[RegClassMax] = {0, 0, 0, 2, 0};
+
+ if (op->reg != 1)
+ emitpcode(PC_FMR, 1, op->reg);
+
+ branch_subroutine(rt_cvt_fp2unsigned, 0, used_regs);
+
+ op->optype = OpndType_GPR;
+ op->reg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MR, op->reg, 3);
+}
+
+void extract_bitfield(Operand *input_op, TypeBitfield *tbitfield, short output_reg, Operand *output_op) {
+ int r27;
+ int offset;
+ int tmp_reg;
+ int output;
+
+ offset = tbitfield->unkB;
+ output = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ r27 = tbitfield->unkA + (32 - (tbitfield->bitfieldtype->size * 8));
+ if (is_unsigned(tbitfield->bitfieldtype)) {
+ emitpcode(PC_RLWINM, output, input_op->reg, (r27 + offset) & 31, 32 - offset, 31);
+ } else if (r27 == 0) {
+ emitpcode(PC_SRAWI, output, input_op->reg, 32 - offset);
+ } else {
+ tmp_reg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, tmp_reg, input_op->reg, r27 & 31, 0, offset);
+ emitpcode(PC_SRAWI, output, tmp_reg, 32 - offset);
+ }
+
+ output_op->optype = OpndType_GPR;
+ output_op->reg = output;
+}
+
+void insert_bitfield(short reg, Operand *op, TypeBitfield *tbitfield) {
+ int offset = tbitfield->unkB;
+ int r7 = tbitfield->unkA + (32 - (tbitfield->bitfieldtype->size * 8));
+ emitpcode(PC_RLWIMI, op->reg, reg, 32 - (r7 + offset), r7, r7 + offset - 1);
+}
+
+void load_address(short dest_reg, Operand *op) {
+ coerce_to_addressable(op);
+ if (op->optype == OpndType_IndirectGPR_ImmOffset) {
+ if (!op->immOffset && !op->object) {
+ if (op->reg != dest_reg) {
+ emitpcode(PC_MR, dest_reg, op->reg);
+ }
+ } else {
+ add_immediate(dest_reg, op->reg, op->object, op->immOffset);
+ }
+ } else if (op->optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(PC_ADD, dest_reg, op->reg, op->regOffset);
+ } else {
+#line 1849
+ CError_FATAL();
+ }
+}
diff --git a/compiler_and_linker/unsorted/PCode.c b/compiler_and_linker/unsorted/PCode.c
new file mode 100644
index 0000000..0fde159
--- /dev/null
+++ b/compiler_and_linker/unsorted/PCode.c
@@ -0,0 +1,299 @@
+#include "compiler.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+
+PCodeBlock *pcbasicblocks;
+PCodeBlock *pclastblock;
+void *prologue;
+void *epilogue;
+PCodeBlock **depthfirstordering;
+int pcblockcount;
+int pcloopweight;
+static unsigned short pclabelcount;
+
+void initpcode() {
+ pclastblock = 0;
+ pcbasicblocks = 0;
+ pcblockcount = 0;
+ pclabelcount = 0;
+ pcloopweight = 1;
+ initialize_aliases();
+}
+
+PCode *makepcode(short op, ...) {
+ PCode *pcode;
+ va_list list;
+
+ va_start(list, op);
+ pcode = vformatpcode(op, list);
+ pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1;
+ return pcode;
+}
+
+void emitpcode(short op, ...) {
+ PCode *pcode;
+ va_list list;
+
+ va_start(list, op);
+ pcode = vformatpcode(op, list);
+ pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1;
+ appendpcode(pclastblock, pcode);
+}
+
+PCode *copypcode(PCode *pcode) {
+ PCode *newpc;
+ int extra_arg;
+ int i;
+
+ extra_arg = 0;
+ if ((PCODE_FLAG_SET_F(pcode) & fPCodeFlag8000000) && !(PCODE_FLAG_SET_F(pcode) & fPCodeFlag20000000))
+ extra_arg = 1;
+
+ newpc = lalloc(sizeof(PCode) + sizeof(PCodeArg) * (pcode->argCount + extra_arg));
+ memclrw(newpc, sizeof(PCode) + sizeof(PCodeArg) * (pcode->argCount + extra_arg));
+
+ newpc->op = pcode->op;
+ newpc->flags = pcode->flags;
+ newpc->argCount = pcode->argCount;
+ newpc->_18 = pcode->_18;
+ for (i = 0; i < pcode->argCount; i++) {
+ newpc->args[i] = pcode->args[i];
+ }
+
+ if (extra_arg)
+ newpc->args[pcode->argCount].kind = PCOp_PLACEHOLDEROPERAND;
+
+ return newpc;
+}
+
+PCodeLabel *makepclabel() {
+ PCodeLabel *label;
+
+ label = (PCodeLabel *) lalloc(sizeof(PCodeLabel));
+ memclrw(label, sizeof(PCodeLabel));
+ label->index = pclabelcount++;
+ return label;
+}
+
+PCodeBlock *makepcblock() {
+ PCodeBlock *block;
+
+ block = (PCodeBlock *) lalloc(sizeof(PCodeBlock));
+ memclrw(block, sizeof(PCodeBlock));
+ block->loopWeight = pcloopweight;
+ block->blockIndex = pcblockcount++;
+ if (pclastblock) {
+ pclastblock->nextBlock = block;
+ block->prevBlock = pclastblock;
+ } else {
+ pcbasicblocks = block;
+ }
+ pclastblock = block;
+ return block;
+}
+
+void pclabel(PCodeBlock *block, PCodeLabel *label) {
+ PCLink *iter;
+ PCLink *next;
+
+ iter = (PCLink *) label->block;
+ while (iter) {
+ next = (PCLink *) iter->block;
+ iter->block = block;
+ iter = next;
+ }
+
+ label->block = block;
+ label->resolved = 1;
+ label->nextLabel = block->labels;
+ block->labels = label;
+}
+
+void pcbranch(PCodeBlock *block, PCodeLabel *label) {
+ PCLink *link;
+
+ link = (PCLink *) lalloc(sizeof(PCLink));
+ memclrw(link, sizeof(PCLink));
+
+ link->block = label->block;
+ if (!label->resolved)
+ label->block = (PCodeBlock *) link;
+ link->nextLink = block->successors;
+ block->successors = link;
+}
+
+void pccomputepredecessors() {
+ PCodeBlock *block;
+ PCLink *succ;
+ PCLink *pred;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (succ = block->successors; succ; succ = succ->nextLink) {
+ pred = (PCLink *) lalloc(sizeof(PCLink));
+ memclrw(pred, sizeof(PCLink));
+
+ pred->block = block;
+ pred->nextLink = succ->block->predecessors;
+ succ->block->predecessors = pred;
+ }
+ }
+}
+
+void deleteblock(PCodeBlock *block) {
+ block->prevBlock->nextBlock = block->nextBlock;
+ if (block->nextBlock)
+ block->nextBlock->prevBlock = block->prevBlock;
+ block->flags |= fPCBlockFlag20;
+}
+
+void deleteunreachableblocks() {
+ PCodeBlock *block;
+
+ computedepthfirstordering();
+
+ for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) {
+ if (!(block->flags & fPCBlockFlag4))
+ deleteblock(block);
+ }
+}
+
+void appendpcode(PCodeBlock *block, PCode *pcode) {
+ if (block->firstPCode) {
+ pcode->nextPCode = 0;
+ pcode->prevPCode = block->lastPCode;
+ block->lastPCode->nextPCode = pcode;
+ block->lastPCode = pcode;
+ } else {
+ block->lastPCode = pcode;
+ block->firstPCode = pcode;
+ pcode->prevPCode = 0;
+ pcode->nextPCode = 0;
+ }
+ pcode->block = block;
+ block->pcodeCount++;
+}
+
+void deletepcode(PCode *pcode) {
+ PCodeBlock *block;
+
+ block = pcode->block;
+ if (pcode->prevPCode)
+ pcode->prevPCode->nextPCode = pcode->nextPCode;
+ else
+ block->firstPCode = pcode->nextPCode;
+ if (pcode->nextPCode)
+ pcode->nextPCode->prevPCode = pcode->prevPCode;
+ else
+ block->lastPCode = pcode->prevPCode;
+
+ pcode->block = 0;
+ block->pcodeCount--;
+ block->flags &= ~fPCBlockFlag8;
+}
+
+void insertpcodebefore(PCode *anchor, PCode *newpcode) {
+ PCodeBlock *block;
+
+ block = anchor->block;
+ if (anchor->prevPCode)
+ anchor->prevPCode->nextPCode = newpcode;
+ else
+ block->firstPCode = newpcode;
+ newpcode->nextPCode = anchor;
+ newpcode->prevPCode = anchor->prevPCode;
+ anchor->prevPCode = newpcode;
+ newpcode->sourceoffset = anchor->sourceoffset;
+
+ newpcode->block = block;
+ block->pcodeCount++;
+ block->flags &= ~fPCBlockFlag8;
+}
+
+void insertpcodeafter(PCode *anchor, PCode *newpcode) {
+ PCodeBlock *block;
+
+ block = anchor->block;
+ if (anchor->nextPCode)
+ anchor->nextPCode->prevPCode = newpcode;
+ else
+ block->lastPCode = newpcode;
+ newpcode->prevPCode = anchor;
+ newpcode->nextPCode = anchor->nextPCode;
+ anchor->nextPCode = newpcode;
+ newpcode->sourceoffset = anchor->sourceoffset;
+
+ newpcode->block = block;
+ block->pcodeCount++;
+ block->flags &= ~fPCBlockFlag8;
+}
+
+void setpcodeflags(int flags) {
+ pclastblock->lastPCode->flags |= flags;
+ if (flags & fSideEffects)
+ pclastblock->lastPCode->flags &= ~(fIsCSE | fCommutative | fPCodeFlag10);
+}
+
+void clearpcodeflags(int flags) {
+ pclastblock->lastPCode->flags &= ~flags;
+}
+
+int pccomputeoffsets() {
+ int offset;
+ PCodeBlock *block;
+
+ offset = 0;
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ block->codeOffset = offset;
+ offset += block->pcodeCount * 4;
+ }
+
+ return offset;
+}
+
+typedef struct _DFO {
+ PCodeBlock *block;
+ PCLink *link;
+} DFO;
+
+static int depthfirstorder;
+
+void computedepthfirstordering() {
+ PCodeBlock *block;
+ PCLink *link;
+ DFO *dfo;
+ int index;
+
+ depthfirstordering = (PCodeBlock **) lalloc(sizeof(PCodeBlock *) * pcblockcount);
+ memclrw(depthfirstordering, sizeof(PCodeBlock *) * pcblockcount);
+ depthfirstorder = pcblockcount;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ block->flags &= ~fPCBlockFlag4;
+ }
+
+ dfo = (DFO *) oalloc(sizeof(DFO) * pcblockcount);
+ pcbasicblocks->flags |= fPCBlockFlag4;
+
+ dfo->block = pcbasicblocks;
+ dfo->link = pcbasicblocks->successors;
+ index = 1;
+ while (index) {
+ if ((link = dfo[index - 1].link)) {
+ dfo[index - 1].link = link->nextLink;
+ block = link->block;
+ if (!(block->flags & fPCBlockFlag4)) {
+ block->flags |= fPCBlockFlag4;
+ dfo[index].block = block;
+ dfo[index].link = block->successors;
+ index++;
+ }
+ } else {
+ depthfirstordering[--depthfirstorder] = dfo[--index].block;
+ }
+ }
+
+ while (depthfirstorder) {
+ depthfirstordering[--depthfirstorder] = 0;
+ }
+}
diff --git a/compiler_and_linker/unsorted/PCodeInfo.c b/compiler_and_linker/unsorted/PCodeInfo.c
new file mode 100644
index 0000000..e48dac0
--- /dev/null
+++ b/compiler_and_linker/unsorted/PCodeInfo.c
@@ -0,0 +1,1308 @@
+#include "compiler.h"
+#include "compiler/objects.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/CError.h"
+
+#pragma pool_strings on
+
+int pcode_bad_operand;
+char *orig_buf;
+static int do_show_basic_blocks;
+
+void pcode_get_hi_lo(int bits, char typechar, SInt32 *hi, SInt32 *lo) {
+ if (bits == 0) {
+ *hi = 0;
+ *lo = 0;
+ return;
+ }
+ if (bits == 32) {
+ *hi = 0x7FFFFFFF;
+ *lo = -0x80000000;
+ return;
+ }
+
+ if (bits < 32 && bits > 0) {
+ switch (typechar) {
+ case 'u':
+ *hi = (1 << bits) - 1;
+ *lo = 0;
+ break;
+ case 'i':
+ case 'x':
+ *hi = (1 << bits) - 1;
+ *lo = -(1 << (bits - 1));
+ break;
+ default:
+ *hi = (1 << (bits - 1)) - 1;
+ *lo = -(1 << (bits - 1));
+ }
+ } else {
+#line 65
+ CError_FATAL();
+ }
+}
+
+int pcode_check_imm_bits(SInt32 value, int bits, char typechar) {
+ char buf[2];
+ int forcedBits;
+ SInt32 r6;
+ SInt32 r0;
+
+ forcedBits = 0;
+ if (bits >= 0 && bits < 32) {
+ if (bits == 0) {
+ r6 = 0;
+ r0 = 0;
+ } else {
+ switch (typechar) {
+ case 'u':
+ r6 = (1 << bits) - 1;
+ r0 = 0;
+ break;
+ case 'i':
+ case 'x':
+ r6 = (1 << bits) - 1;
+ r0 = -(1 << (bits - 1));
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ buf[0] = typechar;
+ buf[1] = 0;
+ forcedBits = atoi(buf);
+ default:
+ r6 = (1 << (bits - 1)) - 1;
+ r0 = -(1 << (bits - 1));
+ }
+ }
+
+ if ((value < r0) || (value > r6))
+ return 1;
+ if (forcedBits > 0 && value != ((value >> forcedBits) << forcedBits))
+ return 1;
+ } else if (bits > 32) {
+#line 110
+ CError_FATAL();
+ }
+
+ return 0;
+}
+
+int pcode_const_from_format(const char *format, int *pResult) {
+ char buf[32];
+ int len = 0;
+
+ for (len = 0; len < 30 && isdigit(format[len]); len++) {
+ buf[len] = format[len];
+ }
+ buf[len] = 0;
+
+ *pResult = atoi(buf);
+ return len;
+}
+
+PCode *vformatpcode(short opcode, va_list argList) {
+ // has many wrong registers but probably ok otherwise
+ int argcount; // r29
+ OpcodeInfo *info; // r27 for a short time
+ int effect; // r27
+ const char *format; // r26
+ PCode *pcode; // r25
+ PCodeArg *arg; // r24
+ int unkreg_r23; // r23
+ int unkreg_r22; // r22
+ PCodeArg *lastArg; // r21
+ int pcode_size; // r20 for a short time
+ int tmp;
+ int tmp2; // r19
+ int i;
+ int thing;
+ int thing2;
+ int thing3;
+ int thing4;
+ Object *obj;
+ PCodeLabel *label;
+ char c;
+
+ info = &opcodeinfo[opcode];
+ format = info->format;
+ argcount = info->x8;
+ unkreg_r23 = 0;
+ unkreg_r22 = 0;
+
+ if (format[0] == '#') {
+ unkreg_r23 = va_arg(argList, int);
+ argcount += unkreg_r23;
+ format++;
+ }
+
+ if (info->flags & fPCodeFlag8000000)
+ unkreg_r22 = 1;
+
+ if ((argcount + unkreg_r22) < 5)
+ unkreg_r22 += 5 - (argcount + unkreg_r22);
+
+ pcode_size = (argcount + unkreg_r22) * sizeof(PCodeArg) + sizeof(PCode);
+ pcode = lalloc(pcode_size);
+ memclrw(pcode, pcode_size);
+
+ pcode->op = opcode;
+ pcode->argCount = argcount;
+ pcode->flags = info->flags;
+ lastArg = pcode->args + pcode->argCount;
+ arg = pcode->args;
+ while (*format) {
+ if (arg >= lastArg) {
+#line 189
+ CError_FATAL();
+ }
+
+ if (*format == ',' || *format == ';')
+ format++;
+ if (*format == '[' || *format == '(')
+ format++;
+
+ effect = EffectRead;
+ if (*format == '=') {
+ effect = EffectWrite;
+ format++;
+ } else if (*format == '+') {
+ effect = EffectRead | EffectWrite;
+ format++;
+ }
+
+ if (*format == '-')
+ format++;
+ if (*format == '?')
+ format++;
+ if (*format == '!')
+ format++;
+
+ switch ((c = *format)) {
+ case 'b':
+ tmp = va_arg(argList, int);
+ if (!tmp)
+ effect = 0;
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_GPR;
+ arg->data.reg.reg = tmp;
+ arg->data.reg.effect = effect;
+ break;
+ case 'r':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_GPR;
+ arg->data.reg.reg = va_arg(argList, int);
+ arg->data.reg.effect = effect;
+ break;
+ case 'f':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_FPR;
+ arg->data.reg.reg = va_arg(argList, int);
+ arg->data.reg.effect = effect;
+ break;
+ case 'v':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_VR;
+ arg->data.reg.reg = va_arg(argList, int);
+ arg->data.reg.effect = effect;
+ break;
+ case 'c':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = va_arg(argList, int);
+ arg->data.reg.effect = effect;
+ break;
+ case 'C':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 2;
+ arg->data.reg.effect = effect;
+ break;
+ case 'L':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 1;
+ arg->data.reg.effect = effect;
+ break;
+ case 'V':
+ i = unkreg_r23;
+ while (i > 0) {
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_GPR;
+ arg->data.reg.reg = 31 - --i;
+ arg->data.reg.effect = effect;
+ arg++;
+ }
+ arg--;
+ break;
+ case 'X':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 0;
+ arg->data.reg.effect = effect;
+ break;
+ case 'Y':
+ if (pcode->op == PC_MTCRF) {
+ tmp = pcode->args[0].data.imm.value;
+ for (i = 0; i < 8; i++) {
+ if (tmp & (0x80 >> i)) {
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = i;
+ arg->data.reg.effect = EffectWrite;
+ arg++;
+ }
+ }
+ } else {
+ i = 0;
+ while (i < 8) {
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = i++;
+ arg->data.reg.effect = EffectRead;
+ arg++;
+ }
+ }
+ arg--;
+ break;
+ case 'Z':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = 0;
+ arg->data.reg.effect = effect;
+ break;
+ case 'P':
+ if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &thing);
+ } else {
+#line 319
+ CError_FATAL();
+ }
+ tmp = va_arg(argList, int);
+ tmp2 = -1;
+ for (i = 0; i < 4; i++) {
+ if (tmp == spr_to_sysreg[i]) {
+ tmp2 = i;
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = i;
+ arg->data.reg.effect = effect;
+ if ((effect & EffectWrite) && (tmp == 0x100))
+ pcsetsideeffects(pcode);
+ break;
+ }
+ }
+
+ if (tmp2 < 0) {
+ pcsetsideeffects(pcode);
+ arg->kind = PCOp_SYSREG;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = tmp;
+ arg->data.reg.effect = effect;
+ }
+
+ break;
+
+ case 'T':
+ tmp = va_arg(argList, int);
+ if (tmp == 0x10C) {
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 0x11C;
+ arg->data.reg.effect = effect;
+ } else if (tmp == 0x10D) {
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 0x11D;
+ arg->data.reg.effect = effect;
+ } else {
+#line 353
+ CError_FATAL();
+ }
+ pcsetsideeffects(pcode);
+ arg->kind = PCOp_SYSREG;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = va_arg(argList, int);
+ arg->data.reg.effect = effect;
+ break;
+
+ case 'S':
+ tmp2 = -1;
+ if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &thing2);
+ } else {
+#line 371
+ CError_FATAL();
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (thing2 == spr_to_sysreg[i]) {
+ tmp2 = i;
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = i;
+ arg->data.reg.effect = effect;
+ if ((effect & EffectWrite) && (thing2 == 0x100))
+ pcsetsideeffects(pcode);
+ break;
+ }
+ }
+
+ if (tmp2 < 0) {
+ pcsetsideeffects(pcode);
+ arg->kind = PCOp_SYSREG;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = va_arg(argList, int);
+ arg->data.reg.effect = effect;
+ }
+ break;
+
+ case 'a':
+ case 'i':
+ case 'n':
+ case 'u':
+ case 'w':
+ case 'x':
+ tmp2 = (unsigned char) c;
+ thing3 = 16;
+ if (*format == 'a') {
+ if (isdigit(format[1])) {
+ tmp2 = (unsigned char) *(++format);
+ } else {
+#line 408
+ CError_FATAL();
+ }
+ }
+ if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &thing3);
+ }
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.value = va_arg(argList, int);
+ arg->data.imm.obj = NULL;
+ if (pcode_check_imm_bits(arg->data.imm.value, thing3, tmp2)) {
+#line 419
+ CError_FATAL();
+ }
+ break;
+
+ case 'N':
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.value = va_arg(argList, int);
+ arg->data.imm.obj = NULL;
+ if (pcode_check_imm_bits(arg->data.imm.value, 6, 'u')) {
+#line 429
+ CError_FATAL();
+ }
+ break;
+
+ case 'D':
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.value = va_arg(argList, int);
+ arg->data.imm.obj = NULL;
+ if (pcode_check_imm_bits(arg->data.imm.value, 10, 'u')) {
+#line 438
+ CError_FATAL();
+ }
+ break;
+
+ case 'B':
+ case 't':
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.value = va_arg(argList, int);
+ arg->data.imm.obj = NULL;
+ if (pcode_check_imm_bits(arg->data.imm.value, 5, 'u')) {
+#line 448
+ CError_FATAL();
+ }
+ break;
+
+ case 'Q':
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = va_arg(argList, int);
+ arg->data.reg.effect = effect;
+ arg++;
+ case 'q':
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.value = va_arg(argList, int);
+ arg->data.imm.obj = NULL;
+ if (pcode_check_imm_bits(arg->data.imm.value, 4, 'u')) {
+#line 463
+ CError_FATAL();
+ }
+ break;
+
+ case 'l':
+ if ((label = va_arg(argList, PCodeLabel *))) {
+ arg->kind = PCOp_LABEL;
+ arg->data.label.label = label;
+ } else {
+ arg->kind = PCOp_MEMORY;
+ obj = va_arg(argList, Object *);
+#line 476
+ CError_ASSERT(obj->otype == OT_OBJECT);
+ arg->data.mem.obj = obj;
+ arg->data.mem.offset = 0;
+ arg->arg = 1;
+ }
+ break;
+
+ case 'd':
+#line 490
+ CError_ASSERT(format[1] == '(');
+ effect = EffectRead;
+ format += 2;
+ if (*format == '=') {
+ effect = EffectWrite;
+ format++;
+ } else if (*format == '+') {
+ effect = EffectRead | EffectWrite;
+ format++;
+ }
+
+#line 502
+ CError_ASSERT(format[0] == 'b');
+
+ tmp = va_arg(argList, int);
+ if (tmp == 0)
+ effect = 0;
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_GPR;
+ arg->data.reg.reg = tmp;
+ arg->data.reg.effect = effect;
+ arg++;
+
+ case 'm':
+ obj = va_arg(argList, Object *);
+ if (obj) {
+#line 515
+ CError_ASSERT(obj->otype == OT_OBJECT);
+
+ if (obj->datatype == DABSOLUTE) {
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.obj = obj;
+ arg->data.imm.value = va_arg(argList, SInt32);
+ } else {
+ arg->kind = PCOp_MEMORY;
+ arg->data.mem.obj = obj;
+ arg->data.mem.offset = va_arg(argList, SInt32);
+
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) {
+ pcode->_18 = make_alias(obj, arg->data.mem.offset, nbytes_loaded_or_stored_by(pcode));
+ if (is_volatile_object(obj))
+ pcode->flags |= fIsVolatile;
+ //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST))
+ if (OBJ_GET_TARGET_CONST(obj))
+ pcode->flags |= fIsConst;
+ } else {
+ if (pcode->op == PC_ADDI)
+ pcode->_18 = make_alias(obj, arg->data.mem.offset, 1);
+ }
+#line 536
+ CError_ASSERT(obj->datatype == DLOCAL || arg->data.mem.offset == 0);
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE))
+ if (OBJ_GET_TARGET_VOLATILE(obj))
+ pcode->flags |= fIsVolatile;
+ //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST))
+ if (OBJ_GET_TARGET_CONST(obj))
+ pcode->flags |= fIsConst;
+ }
+
+ if (pcode->flags & (fPCodeFlag1 | fPCodeFlag8)) {
+ arg->arg = RefType_4;
+ } else if (obj->datatype == DLOCAL) {
+ if (!local_is_16bit_offset(obj))
+ arg->arg = RefType_D;
+ else
+ arg->arg = RefType_1;
+ } else {
+ arg->arg = RefType_6;
+ }
+ }
+ } else {
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.value = va_arg(argList, SInt32);
+ arg->data.imm.obj = NULL;
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4))
+ pcode->flags |= fPCodeFlag20;
+ }
+ break;
+
+ case 'M':
+ obj = va_arg(argList, Object *);
+ if (obj) {
+#line 578
+ CError_ASSERT(obj->otype == OT_OBJECT);
+
+ if (obj->datatype == DABSOLUTE) {
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.obj = obj;
+ arg->data.imm.value = va_arg(argList, SInt32);
+ } else {
+ arg->kind = PCOp_MEMORY;
+ arg->data.mem.obj = obj;
+ arg->data.mem.offset = va_arg(argList, SInt32);
+
+#line 590
+ CError_ASSERT(obj->datatype == DLOCAL || arg->data.mem.offset == 0);
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE))
+ if (OBJ_GET_TARGET_VOLATILE(obj))
+ pcode->flags |= fIsVolatile;
+ //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST))
+ if (OBJ_GET_TARGET_CONST(obj))
+ pcode->flags |= fIsConst;
+ }
+
+ if (obj->datatype == DLOCAL) {
+ arg->arg = RefType_C;
+ } else {
+ arg->arg = RefType_8;
+ }
+ }
+ } else {
+ arg->kind = PCOp_IMMEDIATE;
+ arg->data.imm.value = va_arg(argList, SInt32);
+ arg->data.imm.obj = NULL;
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4))
+ pcode->flags |= fPCodeFlag20;
+ }
+ break;
+
+ case 'p':
+ arg->kind = PCOp_PLACEHOLDEROPERAND;
+ break;
+
+ case 'O':
+ arg--;
+ break;
+
+ default:
+#line 629
+ CError_FATAL();
+ }
+
+ while (format[1] && strchr("/<>|*", format[1])) {
+ switch (*(++format)) {
+ case '/':
+ if (format[1] == '2')
+ format++;
+ break;
+ case '<':
+ case '*':
+ case '|':
+ case '>':
+ if (format[1] == 'p') {
+ format++;
+ } else if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &thing4);
+ } else {
+#line 659
+ CError_FATAL();
+ }
+ }
+ }
+
+ if ((c = *(++format)) == ']' || c == ')')
+ format++;
+ arg++;
+ }
+
+ while (arg < lastArg) {
+ arg->kind = PCOp_PLACEHOLDEROPERAND;
+ arg++;
+ }
+ while (unkreg_r22) {
+ arg->kind = PCOp_PLACEHOLDEROPERAND;
+ arg++;
+ unkreg_r22--;
+ }
+ return pcode;
+}
+
+int expectandformatoperand(PCodeArg *operand, PCOpKind expectedKind, char a3, int bitCount, char *buf) {
+ int errorlen;
+ char *name;
+ int tmp;
+ int regclass;
+ int refis1;
+ int b_null;
+
+ errorlen = 0;
+
+ if (operand->kind != expectedKind) {
+ char *kindstr;
+ switch (expectedKind) {
+ case PCOp_REGISTER: kindstr = "REGISTER"; break;
+ case PCOp_SYSREG: kindstr = "SYSREG"; break;
+ case PCOp_IMMEDIATE: kindstr = "IMMEDIATE"; break;
+ case PCOp_MEMORY: kindstr = "MEMORY"; break;
+ case PCOp_LABEL: kindstr = "LABEL"; break;
+ case PCOp_LABELDIFF: kindstr = "LABELDIFF"; break;
+ case PCOp_PLACEHOLDEROPERAND: kindstr = "PLACEHOLDEROPERAND"; break;
+ default: kindstr = "unknown kind";
+ }
+ tmp = sprintf(buf, "{EXPECTED %s}", kindstr);
+ errorlen += tmp;
+ buf += tmp;
+ pclist_bad_operand = 1;
+ }
+
+ switch (operand->kind) {
+ case PCOp_REGISTER:
+ if (operand->arg != (regclass = a3)) {
+ tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[regclass]);
+ errorlen += tmp;
+ buf += tmp;
+ }
+ if (operand->data.reg.reg < n_real_registers[regclass] && (name = special_register_names[operand->arg][operand->data.reg.reg]))
+ tmp = sprintf(buf, "%s", name);
+ else
+ tmp = sprintf(buf, register_class_format[operand->arg], operand->data.reg.reg);
+ errorlen += tmp;
+ break;
+ case PCOp_SYSREG:
+ if (operand->arg != RegClass_SPR) {
+ tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[RegClass_SPR]);
+ errorlen += tmp;
+ buf += tmp;
+ }
+ tmp = sprintf(buf, register_class_format[RegClass_SPR], operand->data.reg.reg);
+ errorlen += tmp;
+ break;
+ case PCOp_IMMEDIATE:
+ switch (a3) {
+ case 'x':
+ tmp = sprintf(buf, "0x%x", operand->data.imm.value);
+ break;
+ case 'u':
+ tmp = sprintf(buf, "%u", operand->data.imm.value);
+ break;
+ default:
+ tmp = sprintf(buf, "%ld", operand->data.imm.value);
+ break;
+ }
+ errorlen += tmp;
+ buf += tmp;
+ if (operand->data.imm.obj) {
+ name = CMangler_GetLinkName(operand->data.imm.obj)->name;
+ if (strlen(name) > 50)
+ tmp = sprintf(buf, "{%45.45s...}", name);
+ else
+ tmp = sprintf(buf, "{%s}", name);
+ errorlen += tmp;
+ buf += tmp;
+ }
+ if (pcode_check_imm_bits(operand->data.imm.value, bitCount, (char) a3)) {
+ errorlen += sprintf(buf, "{IMM too large %i bits}", bitCount);
+ pclist_bad_operand = 1;
+ }
+ break;
+ case PCOp_MEMORY:
+ switch ((unsigned char) operand->arg) {
+ case RefType_0:
+ case RefType_1:
+ case RefType_2:
+ case RefType_3:
+ case RefType_4:
+ case RefType_5:
+ case RefType_9:
+ break;
+ case RefType_8:
+ case RefType_B:
+ case RefType_C:
+ tmp = sprintf(buf, "HA(");
+ errorlen += tmp;
+ buf += tmp;
+ break;
+ case RefType_7:
+ tmp = sprintf(buf, "HI(");
+ errorlen += tmp;
+ buf += tmp;
+ break;
+ case RefType_6:
+ case RefType_A:
+ case RefType_D:
+ tmp = sprintf(buf, "LO(");
+ errorlen += tmp;
+ buf += tmp;
+ break;
+ default:
+ tmp = sprintf(buf, "{UNEXPECTED reftype = %d}", (unsigned char) operand->arg);
+ errorlen += tmp;
+ buf += tmp;
+ }
+ name = CMangler_GetLinkName(operand->data.mem.obj)->name;
+ if (strlen(name) == 0 || strlen(name) > 3200 || name[0] < 0) {
+#line 849
+ CError_FATAL();
+ }
+ if (strlen(name) > 50)
+ tmp = sprintf(buf, "%45.45s...", name);
+ else
+ tmp = sprintf(buf, "%s", name);
+ errorlen += tmp;
+ buf += tmp;
+ if (operand->data.mem.offset > 0)
+ tmp = sprintf(buf, "+%d", operand->data.mem.offset);
+ else if (operand->data.mem.offset != 0)
+ tmp = sprintf(buf, "-%d", -operand->data.mem.offset);
+ else
+ tmp = 0;
+ errorlen += tmp;
+ buf += tmp;
+ if (copts.codegen_pic && uses_globals && pic_base_reg) {
+ tmp = sprintf(buf, "-B%d", pic_base_pcodelabel->block->blockIndex);
+ errorlen += tmp;
+ buf += tmp;
+ }
+ switch ((unsigned char) operand->arg) {
+ case RefType_6:
+ case RefType_7:
+ case RefType_8:
+ case RefType_A:
+ case RefType_B:
+ case RefType_C:
+ case RefType_D:
+ errorlen += sprintf(buf, ")");
+ }
+ break;
+ case PCOp_LABEL:
+ if (do_show_basic_blocks) {
+ if (!operand->data.label.label->block)
+ tmp = sprintf(buf, "B<unknown>");
+ else
+ tmp = sprintf(buf, "B%ld", operand->data.label.label->block->blockIndex);
+ } else {
+ tmp = sprintf(buf, "%.8lX", operand->data.label.label->block->codeOffset);
+ }
+ errorlen += tmp;
+ break;
+ case PCOp_LABELDIFF:
+ refis1 = ((unsigned char) operand->arg == 1);
+ b_null = !operand->data.labeldiff.labelB->block;
+ if (operand->data.labeldiff.labelA->block == NULL) {
+ if (b_null)
+ tmp = sprintf(buf, "%sB<unknown>-B<unknown>+%ld", refis1 ? "-" : "", operand->data.labeldiff.offset);
+ else
+ tmp = sprintf(buf, "%sB<unknown>-B%ld+%ld", refis1 ? "-" : "", operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset);
+ } else {
+ if (b_null)
+ tmp = sprintf(buf, "%sB%ld-%B<unknown>+%ld", refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.offset);
+ else
+ tmp = sprintf(buf, "%sB%ld-B%ld+%ld", refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset);
+ }
+ errorlen += tmp;
+ break;
+ case PCOp_PLACEHOLDEROPERAND:
+ errorlen += sprintf(buf, "{placeholder}");
+ break;
+ default:
+ errorlen += sprintf(buf, "{UNEXPECTED kind = %d}", operand->kind);
+ }
+
+ return errorlen;
+}
+
+int formatoperand(PCodeArg *operand, char *buf) {
+
+}
+
+void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) {
+ const char *format; // r29
+ // there might be a PCodeArg *arg in r28
+ // not sure lol
+ PCodeArg *pa;
+ int arg_index; // r27
+
+ char *name;
+ int i;
+ int tmp;
+ int tmp2;
+ int thing;
+ int thing2;
+ int thing4;
+ char c;
+ int flagSetT;
+ int flagSetF;
+
+ static char *cc[] = {
+ "lt", "gt", "eq", "un"
+ };
+ static char *to[] = {
+ "", "lgt", "llt", "",
+ "eq", "lge", "lle", "",
+ "gt", "", "", "",
+ "ge", "", "", "",
+ "lt", "", "", "",
+ "le", "", "", "",
+ "ne", "", "", "",
+ "", "", ""
+ };
+
+ format = opcodeinfo[pcode->op].format;
+ orig_buf = buf;
+ do_show_basic_blocks = showBasicBlocks;
+
+ if (format[0] == '#') {
+ format++;
+ if (format[0] == ',')
+ format++;
+ }
+
+ arg_index = 0;
+ pa = pcode->args;
+ while (*format) {
+ if (*format == ';')
+ break;
+ if (arg_index == pcode->argCount) {
+ pclist_bad_operand = 1;
+ buf += sprintf(buf, "{EXCEDED noperands, remaning format = %s}", format);
+ break;
+ }
+
+ if (*format == ',') {
+ *(buf++) = ',';
+ format++;
+ }
+
+ if (*format == '[' || *format == '(') {
+ *(buf++) = *format;
+ format++;
+ }
+
+ if (*format == '=' || *format == '+')
+ format++;
+ if (*format == '-')
+ format++;
+
+ if (*format == '?') {
+ format++;
+ if (*format != 'c')
+ *(buf++) = ',';
+ }
+
+ if (*format == '!')
+ format++;
+
+ switch (*format) {
+ case 'b':
+ if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) {
+ if (pa->data.reg.effect & EffectWrite) {
+ pclist_bad_operand = 1;
+ buf += sprintf(buf, "!!!r");
+ }
+ buf += sprintf(buf, "0");
+ }
+ break;
+ case 'r':
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf);
+ break;
+ case 'f':
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_FPR, -1, buf);
+ break;
+ case 'v':
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_VR, -1, buf);
+ break;
+ case 'c':
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf);
+ break;
+ case 'X':
+#line 1124
+ CError_ASSERT(pa->data.reg.reg == 0);
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf);
+ break;
+ case 'C':
+#line 1129
+ CError_ASSERT(pa->data.reg.reg == 2);
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf);
+ break;
+ case 'L':
+#line 1134
+ CError_ASSERT(pa->data.reg.reg == 1);
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf);
+ break;
+ case 'Z':
+#line 1139
+ CError_ASSERT(pa->data.reg.reg == 0);
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf);
+ break;
+ case 'P':
+ if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &thing);
+ } else {
+#line 1149
+ CError_FATAL();
+ }
+ case 'S':
+ case 'T':
+ case 's':
+ if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_SPR) {
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf);
+ } else {
+ for (i = 0; i < 4; i++) {
+ if (pa->data.reg.reg == spr_to_sysreg[i]) {
+#line 1161
+ CError_FATAL();
+ break;
+ }
+ }
+
+ buf += expectandformatoperand(pa, PCOp_SYSREG, RegClass_SPR, -1, buf);
+ }
+ break;
+
+ case 'V':
+ do {
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf);
+ *(buf++) = ',';
+ pa++;
+ arg_index++;
+ } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR);
+ buf--;
+ pa--;
+ arg_index--;
+ break;
+
+ case 'Y':
+ do {
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf);
+ *(buf++) = ',';
+ pa++;
+ arg_index++;
+ } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_CRFIELD);
+ buf--;
+ pa--;
+ arg_index--;
+ break;
+
+ case 'Q':
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf);
+ *(buf++) = ',';
+ pa++;
+ arg_index++;
+ case 'q':
+ if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value >= 0 && pa->data.imm.value < 4 && (name = cc[pa->data.imm.value])[0]) {
+ buf += sprintf(buf, "%s", name);
+ } else {
+ buf += sprintf(buf, "{OUT OF RANGE}");
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf);
+ }
+ break;
+ case 'a':
+ case 'i':
+ case 'u':
+ case 'x':
+ tmp = *format;
+ if (tmp == 'a') {
+ if (isdigit(format[1])) {
+ format++;
+ tmp = *format;
+ } else {
+#line 1227
+ CError_FATAL();
+ }
+ }
+ if ((tmp2 = isdigit(format[1])))
+ format += pcode_const_from_format(format + 1, &thing2);
+ if (!tmp2)
+ thing2 = -1;
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, tmp, thing2, buf);
+ break;
+
+ case 'N':
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 6, buf);
+ break;
+
+ case 'D':
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 10, buf);
+ break;
+
+ case 't':
+ if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value > 0 && pa->data.imm.value < 31 && (name = to[pa->data.imm.value])[0]) {
+ buf += sprintf(buf, "%s", name);
+ } else {
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'x', 5, buf);
+ }
+ break;
+
+ case 'l':
+ if (pa->kind == PCOp_IMMEDIATE) {
+ buf += sprintf(buf, "*%s%ld", (pa->data.imm.value >= 0) ? "+" : "", pa->data.imm.value);
+ } else if (pa->kind == PCOp_LABELDIFF) {
+ buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf);
+ } else if (pa->kind == PCOp_LABEL) {
+ buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf);
+ } else {
+ buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf);
+ }
+ break;
+
+ case 'd':
+ if (pa[1].kind == PCOp_MEMORY)
+ buf += expectandformatoperand(pa + 1, PCOp_MEMORY, 0, -1, buf);
+ else
+ buf += expectandformatoperand(pa + 1, PCOp_IMMEDIATE, 0, -1, buf);
+#line 1283
+ CError_ASSERT(format[1] == '(');
+ format++;
+ *(buf++) = *(format++);
+ if (*format == '+')
+ format++;
+#line 1291
+ CError_ASSERT(format[0] == 'b');
+ if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) {
+ if (pa->data.reg.effect & (EffectRead | EffectWrite)) {
+ pclist_bad_operand = 1;
+ buf += sprintf(buf, "!!!r");
+ }
+ buf += sprintf(buf, "0");
+ } else {
+ buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf);
+ }
+ pa++;
+ i++;
+ break;
+
+ case 'w':
+ if (pa->kind == PCOp_LABELDIFF)
+ buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf);
+ else
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf);
+ break;
+
+ case 'm':
+ case 'n':
+ if (pa->kind == PCOp_MEMORY)
+ buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf);
+ else if (pa->kind == PCOp_LABELDIFF)
+ buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf);
+ else if ((pcode->flags & (fPCodeFlag1 | fPCodeFlag8)) && (pa->kind == PCOp_LABEL))
+ buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf);
+ else
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf);
+ break;
+
+ case 'M':
+ if (pa->kind == PCOp_MEMORY) {
+#line 1335
+ CError_ASSERT(pa->arg == RefType_8 || pa->arg == RefType_B || pa->arg == RefType_C);
+ buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf);
+ } else if (pa->kind == PCOp_LABELDIFF)
+ buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf);
+ else
+ buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf);
+ break;
+
+ case 'O':
+ pa--;
+ arg_index--;
+ break;
+
+ case 'p':
+ buf += expectandformatoperand(pa, PCOp_PLACEHOLDEROPERAND, 0, -1, buf);
+ break;
+
+ default:
+#line 1465
+ CError_FATAL();
+ }
+
+ while (format[1] && strchr("/<>|*", format[1])) {
+ switch (*(++format)) {
+ case '/':
+ if (format[1] == '2')
+ format++;
+ break;
+ case '<':
+ case '*':
+ case '|':
+ case '>':
+ if (format[1] == 'p') {
+ format++;
+ } else if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &thing4);
+ } else {
+#line 1495
+ CError_FATAL();
+ }
+ }
+ }
+
+ if ((c = *(++format)) == ']' || c == ')') {
+ *(buf++) = c;
+ format++;
+ }
+
+ pa++;
+ arg_index++;
+ }
+
+ if (buf[-1] == ',')
+ buf--;
+
+ flagSetT = PCODE_FLAG_SET_T(pcode);
+ flagSetF = PCODE_FLAG_SET_F(pcode);
+ if (pcode->flags & fIsConst)
+ buf += sprintf(buf, "; fIsConst");
+ if (pcode->flags & fIsVolatile)
+ buf += sprintf(buf, "; fIsVolatile");
+ if (pcode->flags & fSideEffects)
+ buf += sprintf(buf, "; fSideEffects");
+ if (pcode->flags & fIsCSE)
+ buf += sprintf(buf, "; fIsCSE");
+ if (pcode->flags & fCommutative)
+ buf += sprintf(buf, "; fCommutative");
+
+ if (flagSetT & fIsPtrOp)
+ buf += sprintf(buf, "; fIsPtrOp");
+
+ if (flagSetF) {
+ if (flagSetF & fLink)
+ buf += sprintf(buf, "; fLink");
+ if (flagSetF & fAbsolute)
+ buf += sprintf(buf, "; fAbsolute");
+ if (flagSetF & fBranchTaken)
+ buf += sprintf(buf, "; fBranchTaken");
+ if (flagSetF & fBranchNotTaken)
+ buf += sprintf(buf, "; fBranchNotTaken");
+ } else if (flagSetT) {
+ if (flagSetT & fSetsCarry)
+ buf += sprintf(buf, "; fSetsCarry");
+ if (flagSetT & fOverflow)
+ buf += sprintf(buf, "; fOverflow");
+ }
+
+ *buf = 0;
+}
+
+PCode *makecopyinstruction(PCodeArg *a, PCodeArg *b) {
+
+}
+
+int is_location_independent(PCode *pcode) {
+
+}
+
+int can_reuse_stored_value(PCode *a, PCode *b) {
+
+}
+
+int nbytes_loaded_or_stored_by(PCode *pcode) {
+ OpcodeInfo *oinfo = opcodeinfo + pcode->op;
+ if (oinfo->flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ switch (pcode->op) {
+ case PC_LBZ:
+ case PC_LBZU:
+ case PC_LBZX:
+ case PC_LBZUX:
+ case PC_STB:
+ case PC_STBU:
+ case PC_STBX:
+ case PC_STBUX:
+ return 1;
+ case PC_LHZ:
+ case PC_LHZU:
+ case PC_LHZX:
+ case PC_LHZUX:
+ case PC_LHA:
+ case PC_LHAU:
+ case PC_LHAX:
+ case PC_LHAUX:
+ case PC_LHBRX:
+ case PC_STH:
+ case PC_STHU:
+ case PC_STHX:
+ case PC_STHUX:
+ case PC_STHBRX:
+ return 2;
+ case PC_LWZ:
+ case PC_LWZU:
+ case PC_LWZX:
+ case PC_LWZUX:
+ case PC_LWBRX:
+ case PC_STW:
+ case PC_STWU:
+ case PC_STWX:
+ case PC_STWUX:
+ case PC_STWBRX:
+ case PC_LFS:
+ case PC_LFSU:
+ case PC_LFSX:
+ case PC_LFSUX:
+ case PC_STFS:
+ case PC_STFSU:
+ case PC_STFSX:
+ case PC_STFSUX:
+ case PC_LWARX:
+ case PC_STFIWX:
+ case PC_STWCX:
+ case PC_ECIWX:
+ case PC_ECOWX:
+ case PC_MFROM:
+ case PC_LSCBX:
+ return 4;
+ case PC_LMW:
+ case PC_STMW:
+ if (pcode->args[0].kind == PCOp_REGISTER && pcode->args[0].arg == RegClass_GPR)
+ return (32 - pcode->args[0].data.reg.reg) * 4;
+ else
+ return 128;
+ case PC_LFD:
+ case PC_LFDU:
+ case PC_LFDX:
+ case PC_LFDUX:
+ case PC_STFD:
+ case PC_STFDU:
+ case PC_STFDX:
+ case PC_STFDUX:
+ return 8;
+ case PC_LSWI:
+ case PC_STSWI:
+ return pcode->args[2].data.imm.value; // not sure if imm is the right union type here
+ case PC_LSWX:
+ case PC_STSWX:
+ return 128;
+
+ // there's probably an ifdef here lmao
+ case PC_LVEBX:
+ case PC_STVEBX:
+ return 1;
+ case PC_LVEHX:
+ case PC_STVEHX:
+ return 2;
+ case PC_LVEWX:
+ case PC_STVEWX:
+ return 4;
+ case PC_LVSL:
+ case PC_LVSR:
+ case PC_LVX:
+ case PC_LVXL:
+ case PC_STVX:
+ case PC_STVXL:
+ return 16;
+
+ default:
+#line 2011
+ CError_FATAL();
+ }
+ }
+
+#line 2014
+ CError_FATAL();
+ return 0;
+}
+
+void change_num_operands(PCode *pcode, int newNum) {
+
+}
+
+void change_opcode(PCode *pcode, short opcode) {
+ pcode->flags = (pcode->flags & ~(opcodeinfo[pcode->op].flags & ~fIsPtrOp)) | opcodeinfo[opcode].flags;
+ if ((pcode->flags & fPCodeFlag10) && (PCODE_FLAG_SET_F(pcode) & fPCodeFlag20000000))
+ pcode->flags &= ~fPCodeFlag10;
+ pcode->op = opcode;
+}
diff --git a/compiler_and_linker/unsorted/PCodeUtilities.c b/compiler_and_linker/unsorted/PCodeUtilities.c
new file mode 100644
index 0000000..b0191e9
--- /dev/null
+++ b/compiler_and_linker/unsorted/PCodeUtilities.c
@@ -0,0 +1,348 @@
+#include "compiler/PCodeUtilities.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/CError.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler.h"
+
+void pcsetrecordbit(PCode *pc) {
+ int reg;
+ PCodeArg *arg;
+ short argCount;
+ int argIdx;
+
+ pc->flags &= ~(fPCodeFlag10 | fCommutative | fIsCSE);
+ if ((pc->flags & (fPCodeFlag80000000 | fPCodeFlag40000000)) == fPCodeFlag40000000) {
+ reg = 1;
+ } else if ((pc->flags & (fPCodeFlag80000000 | fPCodeFlag40000000)) == (fPCodeFlag80000000 | fPCodeFlag40000000)) {
+ reg = 6;
+ } else {
+ reg = 0;
+ }
+
+ if (pc->op == PC_ANDI || pc->op == PC_ANDIS) {
+ pc->flags |= fPCodeFlag20000000;
+ } else if (pc->op == PC_ADDI || pc->op == PC_ADDIC) {
+ pc->flags |= fPCodeFlag10000000;
+ pc->flags |= fPCodeFlag20000000;
+ change_num_operands(pc, 5);
+ pc->op = PC_ADDICR;
+
+#line 76
+ CError_ASSERT(pc->args[3].kind == PCOp_PLACEHOLDEROPERAND);
+ pc->args[3].kind = PCOp_REGISTER;
+ pc->args[3].arg = RegClass_SPR;
+ pc->args[3].data.reg.reg = 0;
+ pc->args[3].data.reg.effect = EffectWrite;
+#line 80
+ CError_ASSERT(pc->args[4].kind == PCOp_PLACEHOLDEROPERAND);
+ pc->args[4].kind = PCOp_REGISTER;
+ pc->args[4].arg = RegClass_CRFIELD;
+ pc->args[4].data.reg.reg = reg;
+ pc->args[4].data.reg.effect = EffectWrite;
+ } else {
+ arg = pc->args;
+ argIdx = argCount = pc->argCount;
+ while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) {
+ if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_CRFIELD && arg->data.reg.reg == reg) {
+ arg->data.reg.effect |= EffectWrite;
+ pc->flags |= fPCodeFlag20000000;
+ return;
+ }
+ arg++;
+ argIdx--;
+ }
+
+ if (argIdx <= 0) {
+ arg = &pc->args[argCount];
+ pc->argCount++;
+ }
+
+#line 105
+ CError_ASSERT(arg->kind == PCOp_PLACEHOLDEROPERAND);
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = reg;
+ arg->data.reg.effect = EffectWrite;
+ if (pc->op != PC_ADDICR)
+ pc->flags |= fPCodeFlag20000000;
+ }
+}
+
+void pcsetsideeffects(PCode *pc) {
+ pc->flags &= ~(fPCodeFlag10 | fCommutative | fIsCSE);
+ pc->flags |= fSideEffects;
+}
+
+void pcsetlinkbit(PCode *pc) {
+ PCodeArg *arg;
+ int argIdx;
+
+ switch (pc->op) {
+ case PC_B:
+ pc->op = PC_BL;
+ break;
+ case PC_BCTR:
+ pc->op = PC_BCTRL;
+ break;
+ case PC_BLR:
+ pc->op = PC_BLRL;
+ break;
+ }
+
+ arg = pc->args;
+ argIdx = pc->argCount;
+ while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) {
+ if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_SPR && arg->data.reg.reg == 1) {
+ arg->data.reg.effect |= EffectWrite;
+ pc->flags |= fLink;
+ return;
+ }
+ arg++;
+ argIdx--;
+ }
+
+#line 169
+ CError_ASSERT(arg->kind == PCOp_PLACEHOLDEROPERAND);
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 1;
+ arg->data.reg.effect = EffectWrite;
+
+ if (opcodeinfo[pc->op].flags & fPCodeFlag8) {
+ pc->flags &= ~fPCodeFlag1;
+ pc->flags |= fPCodeFlag8;
+ }
+ pc->flags |= fLink;
+}
+
+void branch_label(PCodeLabel *label) {
+ if (pclastblock->pcodeCount) {
+ pcbranch(pclastblock, label);
+ makepcblock();
+ }
+ pclabel(pclastblock, label);
+}
+
+void branch_conditional(short a, short compareop, short c, PCodeLabel *label) {
+ PCodeBlock *tmpblock;
+ PCodeLabel *tmplabel;
+ int r28;
+
+ tmpblock = pclastblock;
+ tmplabel = makepclabel();
+
+ switch (compareop) {
+ case ENOTEQU:
+ c = !c;
+ case EEQU:
+ r28 = 2;
+ break;
+ case EGREATEREQU:
+ c = !c;
+ case ELESS:
+ r28 = 0;
+ break;
+ case ELESSEQU:
+ c = !c;
+ case EGREATER:
+ r28 = 1;
+ break;
+ }
+
+ emitpcode(c ? PC_BT : PC_BF, a, r28, label);
+ pcbranch(pclastblock, label);
+ pcbranch(pclastblock, tmplabel);
+ makepcblock();
+ pclabel(pclastblock, tmplabel);
+}
+
+void branch_always(PCodeLabel *label) {
+ emitpcode(PC_B, label);
+ pcbranch(pclastblock, label);
+ makepcblock();
+}
+
+void branch_decrement_always(short opcode, PCodeLabel *label) {
+ PCodeLabel *tmplabel = makepclabel();
+ emitpcode(opcode, label);
+ pcbranch(pclastblock, label);
+ pcbranch(pclastblock, tmplabel);
+ makepcblock();
+ pclabel(pclastblock, tmplabel);
+}
+
+void branch_indirect(Object *obj) {
+ emitpcode(PC_BCTR, obj, 0);
+ makepcblock();
+}
+
+int branch_count_volatiles(void) {
+ int count = 0;
+ int i;
+ char rclass;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ for (i = 0; i < n_scratch_registers[(char)rclass]; i++) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks) {
+ int i;
+ char rclass;
+
+ for (rclass = RegClassMax - 1; rclass >= 0; rclass--) {
+ for (i = 0; i < n_scratch_registers[(char)rclass]; i++) {
+ arglist->kind = PCOp_REGISTER;
+ arglist->arg = rclass;
+ arglist->data.reg.reg = scratch_registers[(char)rclass][i];
+ arglist->data.reg.effect = EffectWrite;
+ if (masks[(char)rclass] & (1 << scratch_registers[(char)rclass][i]))
+ arglist->data.reg.effect |= EffectRead;
+ arglist++;
+ }
+ }
+
+ return arglist;
+}
+
+void branch_subroutine(Object *obj, short add_nop, UInt32 *masks) {
+ int count;
+ PCode *pc;
+ PCodeArg *arg;
+
+ count = branch_count_volatiles();
+ if (copts.exceptions && current_statement)
+ count += countexceptionactionregisters(current_statement->dobjstack);
+
+ pc = makepcode(PC_BL, count, obj, 0);
+ arg = branch_record_volatiles(pc->args + 1, masks);
+ if (copts.exceptions && current_statement)
+ noteexceptionactionregisters(current_statement->dobjstack, arg);
+ appendpcode(pclastblock, pc);
+
+ if (add_nop)
+ emitpcode(PC_NOP);
+
+ branch_label(makepclabel());
+ if (copts.exceptions && current_statement)
+ recordexceptionactions(pc, current_statement->dobjstack);
+}
+
+void branch_subroutine_ctr(UInt32 *masks) {
+ int count;
+ PCode *pc;
+ PCodeArg *arg;
+
+ count = branch_count_volatiles();
+ if (copts.exceptions && current_statement)
+ count += countexceptionactionregisters(current_statement->dobjstack);
+
+ pc = makepcode(PC_BCTRL, count);
+ arg = branch_record_volatiles(pc->args + 1, masks);
+ if (copts.exceptions && current_statement)
+ noteexceptionactionregisters(current_statement->dobjstack, arg);
+ appendpcode(pclastblock, pc);
+
+ branch_label(makepclabel());
+ if (copts.exceptions && current_statement)
+ recordexceptionactions(pc, current_statement->dobjstack);
+}
+
+void add_immediate(short dest_reg, short base_reg, Object *obj, short offset) {
+ short tmp_reg = base_reg;
+
+ if (obj && offset && obj->datatype != DLOCAL) {
+ tmp_reg = used_virtual_registers[RegClass_GPR]++;
+ add_immediate_lo(tmp_reg, base_reg, obj, 0, 1);
+ obj = NULL;
+ }
+
+ if (!obj && !offset)
+ emitpcode(PC_MR, dest_reg, tmp_reg);
+ else
+ emitpcode(PC_ADDI, dest_reg, tmp_reg, obj, offset);
+}
+
+PCode *add_immediate_lo(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) {
+ PCode *pc;
+
+#line 577
+ CError_ASSERT(obj);
+
+ pc = makepcode(PC_ADDI, dest_reg, base_reg, obj, offset);
+ if (add_to_block)
+ appendpcode(pclastblock, pc);
+ return pc;
+}
+
+PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) {
+ PCode *pc;
+ int tmp_reg;
+
+ if (obj->datatype == DLOCAL) {
+ pc = makepcode(PC_ADDIS, dest_reg, base_reg, obj, offset);
+ } else if (copts.codegen_pic) {
+ tmp_reg = base_reg;
+#line 601
+ CError_ASSERT(tmp_reg);
+ pc = makepcode(PC_ADDIS, dest_reg, tmp_reg, obj, offset);
+ } else {
+#line 606
+ CError_ASSERT(base_reg == 0);
+ pc = makepcode(PC_LIS, dest_reg, obj, offset);
+ }
+
+ if (add_to_block)
+ appendpcode(pclastblock, pc);
+ return pc;
+}
+
+void load_store_register(short opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) {
+ short addi_tmp;
+ short offset_reg1;
+ short offset_reg2;
+
+ offset_reg1 = base_reg;
+ if (obj && offset && obj->datatype != DLOCAL) {
+ offset_reg1 = used_virtual_registers[RegClass_GPR]++;
+ add_immediate_lo(offset_reg1, base_reg, obj, 0, 1);
+ obj = NULL;
+ }
+
+ if (offset != (short)offset) {
+ if (opcode == PC_LWZ && dest_reg == 12)
+ offset_reg2 = 12;
+ else if (opcode == PC_LWZ && dest_reg == 11)
+ offset_reg2 = 11;
+ else
+ offset_reg2 = used_virtual_registers[RegClass_GPR]++;
+
+ emitpcode(PC_ADDIS, offset_reg2, offset_reg1, 0, (short) ((offset >> 16) + ((offset & 0x8000) >> 15)));
+ offset = (short) offset;
+ offset_reg1 = offset_reg2;
+ }
+
+ if (opcode == PC_STVX || opcode == PC_LVX) {
+ offset_reg2 = 0;
+ if (obj) {
+ addi_tmp = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADDI, addi_tmp, offset_reg1, obj, offset);
+ offset_reg1 = addi_tmp;
+ } else if (offset) {
+ offset_reg2 = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LI, offset_reg2, offset);
+ }
+ if (!offset_reg2)
+ emitpcode(opcode, dest_reg, 0, offset_reg1);
+ else
+ emitpcode(opcode, dest_reg, offset_reg1, offset_reg2);
+ } else {
+ emitpcode(opcode, dest_reg, offset_reg1, obj, offset);
+ }
+}
diff --git a/compiler_and_linker/unsorted/RegisterInfo.c b/compiler_and_linker/unsorted/RegisterInfo.c
new file mode 100644
index 0000000..c1e67d8
--- /dev/null
+++ b/compiler_and_linker/unsorted/RegisterInfo.c
@@ -0,0 +1,392 @@
+#include "compiler.h"
+#include "compiler/CError.h"
+#include "compiler/objects.h"
+#include "compiler/PCode.h"
+
+short last_exception_register[RegClassMax];
+short first_fe_temporary_register[RegClassMax];
+short last_argument_register[RegClassMax];
+short _FP_;
+short _CALLER_SP_;
+char *special_register_names[RegClassMax][RegisterMax];
+static short used_regs_before_coloring;
+static UInt8 save_state[RegisterMax];
+
+char *XXspecial_register_names[RegClassMax * RegisterMax];
+
+short spr_to_sysreg[4] = {1, 8, 9, 0x100};
+
+void asm_used_register(char rclass, short reg) {
+ int i;
+
+ if ((reg < n_real_registers[rclass]) && (reg_state[rclass][reg] == RegState0)) {
+ if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) {
+ if (assignable_registers[rclass] > 0)
+ assignable_registers[rclass]--;
+ reg_state[rclass][reg] = RegState1;
+ used_nonvolatile_registers[rclass]++;
+ } else {
+ for (i = used_nonvolatile_registers[rclass]; i < n_nonvolatile_registers[rclass]; i++) {
+ if (reg == nonvolatile_registers[rclass][i]) {
+ reg_state[rclass][reg] = RegState1;
+ if (assignable_registers[rclass] > 0)
+ assignable_registers[rclass]--;
+ }
+ }
+ }
+ }
+}
+
+void retain_register(Object *obj, char rclass, short reg) {
+ VarInfo *vi;
+
+#line 95
+ CError_ASSERT((short) reg < RegisterMax);
+
+ if (reg_state[rclass][reg] == RegState0) {
+ assignable_registers[rclass]--;
+ reg_state[rclass][reg] = RegState1;
+ if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]])
+ used_nonvolatile_registers[rclass]++;
+ }
+
+ if (obj) {
+ vi = Registers_GetVarInfo(obj);
+ vi->rclass = rclass;
+ vi->flags |= VarInfoFlag2;
+ vi->reg = reg;
+ }
+}
+
+void retain_GPR_pair(Object *obj, short reg, short regHi) {
+ VarInfo *vi;
+
+ retain_register(NULL, RegClass_GPR, reg);
+ retain_register(NULL, RegClass_GPR, regHi);
+
+ if (obj) {
+ vi = Registers_GetVarInfo(obj);
+ vi->rclass = RegClass_GPR;
+ vi->flags |= VarInfoFlag2 | VarInfoFlag4;
+ vi->reg = reg;
+ vi->regHi = regHi;
+ }
+}
+
+int is_register_object(Object *obj) {
+ return obj->sclass == OBJECT_SCLASS_101;
+}
+
+int GetABIFirstNonVolatile(char rclass) {
+ switch (rclass) {
+ case RegClass_SPR: return 3;
+ case RegClass_CRFIELD: return 2;
+ case RegClass_VR: return 20;
+ case RegClass_GPR: return 13;
+ case RegClass_FPR: return 14;
+ default: return -1;
+ }
+}
+
+char GetRegisterClassName(char rclass) {
+ switch (rclass) {
+ case RegClass_VR: return 'v';
+ case RegClass_GPR: return 'r';
+ case RegClass_FPR: return 'f';
+ default:
+#line 242
+ CError_FATAL();
+ return '?';
+ }
+}
+
+static int first_nonvolatile_reg(char rclass) {
+ return GetABIFirstNonVolatile(rclass);
+}
+
+void setup_diagnostic_reg_strings() {
+ register_class_name[RegClass_SPR] = "SPR";
+ register_class_format[RegClass_SPR] = "spr%ld";
+ register_class_name[RegClass_CRFIELD] = "CRFIELD";
+ register_class_format[RegClass_CRFIELD] = "cr%ld";
+ register_class_name[RegClass_VR] = "VR";
+ register_class_format[RegClass_VR] = "vr%ld";
+ register_class_name[RegClass_FPR] = "FPR";
+ register_class_format[RegClass_FPR] = "f%ld";
+ register_class_name[RegClass_GPR] = "GPR";
+ register_class_format[RegClass_GPR] = "r%ld";
+}
+
+void init_target_registers() {
+ char rclass;
+ int reg;
+ int end;
+ int tmp;
+
+ static int last_nonvolatile_reg[] = {3, 5, 31, 31, 31};
+ static int nonvol_reserve[] = {0, 0, 0, 4, 3};
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ for (reg = 0; reg < RegisterMax; reg++)
+ special_register_names[(char)rclass][reg] = NULL;
+ }
+
+ special_register_names[RegClass_SPR][0] = "XER";
+ special_register_names[RegClass_SPR][1] = "LR";
+ special_register_names[RegClass_SPR][2] = "CTR";
+ special_register_names[RegClass_SPR][3] = "VRSAVE";
+ special_register_names[RegClass_GPR][1] = "SP";
+
+ setup_diagnostic_reg_strings();
+ n_real_registers[RegClass_SPR] = 4;
+ n_real_registers[RegClass_CRFIELD] = 8;
+ n_real_registers[RegClass_VR] = 32;
+ n_real_registers[RegClass_FPR] = 32;
+ n_real_registers[RegClass_GPR] = 32;
+ reg_state[RegClass_GPR][1] = RegState2;
+ reg_state[RegClass_GPR][2] = RegState2;
+ reg_state[RegClass_CRFIELD][5] = RegState2;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ n_nonvolatile_registers[(char)rclass] = 0;
+ if (last_nonvolatile_reg[(char)rclass] >= 0) {
+ end = first_nonvolatile_reg(rclass);
+ for (reg = last_nonvolatile_reg[(char)rclass]; reg >= end; reg--) {
+ if (reg_state[(char)rclass][reg] == RegState0) {
+ tmp = n_nonvolatile_registers[(char)rclass]++;
+ nonvolatile_registers[(char)rclass][tmp] = reg;
+ }
+ }
+ }
+
+ assignable_registers[(char)rclass] = n_nonvolatile_registers[(char)rclass] - nonvol_reserve[(char)rclass];
+ if (assignable_registers[(char)rclass] < 0)
+ assignable_registers[(char)rclass] = 0;
+
+ n_scratch_registers[(char)rclass] = 0;
+ for (reg = 0; reg < n_real_registers[(char)rclass]; reg++) {
+ if (reg < GetABIFirstNonVolatile(rclass) || reg > last_nonvolatile_reg[(char)rclass]) {
+ if (reg_state[(char)rclass][reg] == RegState0) {
+ tmp = n_scratch_registers[(char)rclass]++;
+ scratch_registers[(char)rclass][tmp] = reg;
+ }
+ }
+ }
+ }
+
+ _FP_ = -1;
+ _CALLER_SP_ = -1;
+ optimizing = (copts.optimizationlevel > 0) && !disable_optimizer;
+}
+
+void assign_register_by_type(Object *obj) {
+ VarInfo *vi;
+ Type *ty;
+ Boolean flag;
+
+ ty = obj->type;
+ vi = Registers_GetVarInfo(obj);
+ flag = 0;
+ vi->rclass = RegClassMax;
+ vi->reg = 0;
+ vi->regHi = 0;
+
+ if ((ty->type == TYPEINT) || (ty->type == TYPEENUM) || ((ty->type == TYPEPOINTER || ty->type == TYPEARRAY) && (ty->type != TYPEARRAY)) || ((ty->type == TYPEMEMBERPOINTER) && (ty->size == 4U))) {
+ if (((ty->type == TYPEINT) || (ty->type == TYPEENUM)) && (ty->size == 8))
+ flag = 1;
+ vi->rclass = RegClass_GPR;
+ } else if (ty->type == TYPEFLOAT) {
+ vi->rclass = RegClass_FPR;
+ } else if ((ty->type == TYPESTRUCT) && (TYPE_STRUCT(ty)->stype >= STRUCT_TYPE_4) && (TYPE_STRUCT(ty)->stype <= STRUCT_TYPE_E)) {
+ vi->rclass = RegClass_VR;
+ } else {
+ return;
+ }
+
+ if (vi->rclass < RegClassMax) {
+ if (flag) {
+#line 520
+ CError_ASSERT(vi->rclass == RegClass_GPR);
+ if (assignable_registers[vi->rclass] > 1)
+ assign_GPR_pair(obj);
+ } else {
+ if (assignable_registers[vi->rclass] > 0)
+ assign_register_to_variable(obj, vi->rclass);
+ }
+ }
+}
+
+void assign_GPR_pair(Object *obj) {
+ VarInfo *vi;
+ short reg;
+ short regHi;
+
+ vi = Registers_GetVarInfo(obj);
+ if (optimizing) {
+ reg = used_virtual_registers[RegClass_GPR]++;
+ regHi = used_virtual_registers[RegClass_GPR]++;
+ } else {
+#line 554
+ CError_ASSERT(assignable_registers[RegClass_GPR] >= 2);
+ reg = obtain_nonvolatile_register(RegClass_GPR);
+ regHi = obtain_nonvolatile_register(RegClass_GPR);
+ retain_GPR_pair(obj, reg, regHi);
+ }
+
+ vi->rclass = RegClass_GPR;
+ if (reg > 0 && regHi > 0) {
+ vi->flags |= VarInfoFlag2 | VarInfoFlag4;
+ vi->reg = reg;
+ vi->regHi = regHi;
+ } else {
+#line 567
+ CError_FATAL();
+ }
+}
+
+void open_fe_temp_registers() {
+ int r;
+
+ r = used_virtual_registers[RegClass_GPR];
+ first_fe_temporary_register[RegClass_GPR] = last_temporary_register[RegClass_GPR] = r;
+ r = used_virtual_registers[RegClass_FPR];
+ first_fe_temporary_register[RegClass_FPR] = last_temporary_register[RegClass_FPR] = r;
+ r = used_virtual_registers[RegClass_VR];
+ first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = r;
+ //first_fe_temporary_register[RegClass_GPR] = last_temporary_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR];
+ //first_fe_temporary_register[RegClass_FPR] = last_temporary_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR];
+ //first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = used_virtual_registers[RegClass_VR];
+}
+
+void set_last_exception_registers() {
+ last_exception_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR] - 1;
+ last_exception_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR] - 1;
+ last_exception_register[RegClass_VR] = used_virtual_registers[RegClass_VR] - 1;
+}
+
+static VarInfo *Registers_GetNewVarInfo() {
+ VarInfo *vi = galloc(sizeof(VarInfo));
+ memclrw(vi, sizeof(VarInfo));
+ return vi;
+}
+
+VarInfo *Registers_GetVarInfo(Object *obj) {
+ switch (obj->datatype) {
+ case DDATA:
+ if (!obj->u.data.info)
+ obj->u.data.info = Registers_GetNewVarInfo();
+ return obj->u.data.info;
+ case DNONLAZYPTR:
+ // not sure if this is the right union
+ if (!obj->u.toc.info) {
+#line 639
+ CError_FATAL();
+ obj->u.toc.info = CodeGen_GetNewVarInfo();
+ }
+ return obj->u.toc.info;
+ case DLOCAL:
+ if (!obj->u.var.info) {
+#line 647
+ CError_FATAL();
+ }
+ return obj->u.var.info;
+ case DABSOLUTE:
+ // not sure if this is the right union
+ if (!obj->u.data.info)
+ obj->u.data.info = Registers_GetNewVarInfo();
+ return obj->u.data.info;
+ default:
+#line 660
+ CError_FATAL();
+ return NULL;
+ }
+}
+
+int used_vrstate_VRs() {
+ int count = 0;
+ int i;
+ for (i = 0; i < RegisterMax; i++) {
+ if (reg_state[RegClass_VR][i])
+ count++;
+ }
+ return count;
+}
+
+UInt32 colored_vrs_as_vrsave(PCodeBlock *block) {
+ PCode *pc;
+ UInt32 mask;
+ int i;
+
+ mask = 0;
+ if (copts.x1B == 2)
+ return 0xFFFFFFFF;
+ if (copts.x1B == 0)
+ return 0;
+
+ while (block) {
+ for (pc = block->firstPCode; pc; pc = pc->nextPCode) {
+ if (pc->flags & (fPCodeFlag40000000 | fPCodeFlag80000000)) {
+ for (i = 0; i < pc->argCount; i++) {
+ if (pc->args[i].kind == PCOp_REGISTER && pc->args[i].arg == RegClass_VR)
+ mask |= 1 << (31 - pc->args[i].data.reg.reg);
+ }
+ }
+ }
+ block = block->nextBlock;
+ }
+
+ return mask;
+}
+
+void save_before_coloring_nonvolatile_registers(char rclass) {
+ used_regs_before_coloring = used_nonvolatile_registers[rclass];
+ memcpy(save_state, reg_state[rclass], sizeof(save_state));
+}
+
+void reset_nonvolatile_registers(char rclass) {
+ used_nonvolatile_registers[rclass] = used_regs_before_coloring;
+ memcpy(reg_state[rclass], save_state, sizeof(save_state));
+}
+
+int is_nonvolatile_register(char rclass, int reg) {
+ int i;
+
+ for (i = 0; i < n_nonvolatile_registers[rclass]; i++) {
+ if (reg == nonvolatile_registers[rclass][i])
+ return 1;
+ }
+
+ return 0;
+}
+
+void init_endian() {
+ if (copts.little_endian) {
+ high_offset = 4;
+ low_offset = 0;
+ high_reg = 4;
+ low_reg = 3;
+ high_reg2 = 6;
+ low_reg2 = 5;
+ } else {
+ high_offset = 0;
+ low_offset = 4;
+ high_reg = 3;
+ low_reg = 4;
+ high_reg2 = 5;
+ low_reg2 = 6;
+ }
+}
+
+void update_asm_nonvolatile_registers() {
+ char rclass;
+ int r31;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ for (r31 = n_nonvolatile_registers[rclass] - 1; r31 >= 0; r31--) {
+ if (reg_state[rclass][nonvolatile_registers[rclass][r31]] == RegState1)
+ break;
+ }
+ if (r31 > used_nonvolatile_registers[rclass])
+ used_nonvolatile_registers[rclass] = r31;
+ }
+}
diff --git a/compiler_and_linker/unsorted/Registers.c b/compiler_and_linker/unsorted/Registers.c
new file mode 100644
index 0000000..9bcbf05
--- /dev/null
+++ b/compiler_and_linker/unsorted/Registers.c
@@ -0,0 +1,225 @@
+#include "compiler.h"
+#include "compiler/objects.h"
+#include "compiler/PCode.h"
+
+// haven't checked this object file for .data stuff yet
+
+// ONLY FOR TESTING
+// this file gets kinda fucked up by the loop unroller
+//#pragma opt_unroll_loops off
+
+int used_virtual_registers[RegClassMax];
+int used_nonvolatile_registers[RegClassMax];
+int assignable_registers[RegClassMax];
+int n_real_registers[RegClassMax];
+int n_scratch_registers[RegClassMax];
+int scratch_registers[RegClassMax][RegisterMax];
+int n_nonvolatile_registers[RegClassMax];
+int nonvolatile_registers[RegClassMax][RegisterMax];
+UInt8 reg_state[RegClassMax][RegisterMax];
+int first_temporary_register[RegClassMax];
+int last_temporary_register[RegClassMax];
+char *register_class_name[RegClassMax];
+char *register_class_format[RegClassMax];
+int coloring;
+int optimizing;
+typedef struct ModifiedRegisters {
+ struct ModifiedRegisters *next;
+ Object *obj;
+ UInt32 mask[RegClassMax];
+} ModifiedRegisters;
+static ModifiedRegisters *mod_regs_table[128];
+
+void init_registers() {
+ char rclass;
+ int j;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ for (j = 0; j < RegisterMax; j++) {
+ reg_state[(char)rclass][j] = RegState0;
+ }
+ }
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ used_nonvolatile_registers[(char)rclass] = 0;
+
+ optimizing = 1;
+
+ init_target_registers();
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ used_virtual_registers[(char)rclass] = n_real_registers[(char)rclass];
+
+ coloring = 1;
+}
+
+void assign_register_to_variable(Object *obj, char rclass) {
+ VarInfo *vi;
+ short reg;
+
+ vi = Registers_GetVarInfo(obj);
+ if (optimizing) {
+ reg = used_virtual_registers[rclass]++;
+ } else {
+ reg = obtain_nonvolatile_register(rclass);
+ retain_register(obj, rclass, reg);
+ }
+
+ vi->flags |= VarInfoFlag2;
+ vi->rclass = rclass;
+ vi->reg = reg;
+}
+
+void retain_register_for_argument(Object *obj, char rclass, short reg) {
+ VarInfo *vi = obj->u.var.info;
+ reg_state[rclass][reg] = RegState1;
+ vi->flags |= VarInfoFlag2;
+ vi->rclass = rclass;
+ vi->reg = reg;
+}
+
+int available_registers(char rclass) {
+ int i;
+ int count = 0;
+
+ for (i = 0; i < n_real_registers[rclass]; i++) {
+ if (reg_state[rclass][i] == RegState0)
+ count++;
+ }
+
+ return count;
+}
+
+UInt32 volatile_registers(char rclass) {
+ UInt32 mask = 0;
+ int i;
+ int reg;
+
+ for (i = 0; i < n_scratch_registers[rclass]; i++) {
+ reg = scratch_registers[rclass][i];
+ if (reg_state[rclass][reg] == RegState0)
+ mask |= 1 << reg;
+ }
+
+ return mask;
+}
+
+short obtain_nonvolatile_register(char rclass) {
+ int best = -1;
+
+ while (used_nonvolatile_registers[rclass] < n_nonvolatile_registers[rclass]) {
+ int tmp = nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]++];
+ if (reg_state[rclass][tmp] == RegState0) {
+ best = tmp;
+ break;
+ }
+ }
+
+ return best;
+}
+
+void open_temp_registers() {
+ int rclass;
+
+ for (rclass = 0; (char)rclass < RegClassMax; rclass++) {
+ int r = used_virtual_registers[(char)rclass];
+ //last_temporary_register[rclass] = r;
+ //first_temporary_register[rclass] = r;
+ first_temporary_register[(char)rclass] = last_temporary_register[(char)rclass] = r;
+ }
+ /*rclass = 0;
+ while (rclass < RegClassMax) {
+ r = used_virtual_registers[(char)rclass];
+ last_temporary_register[(char)rclass] = r;
+ first_temporary_register[(char)rclass] = r;
+ rclass = rclass + 1;
+ }*/
+}
+
+void check_temp_registers() {
+ char rclass;
+
+ if (!optimizing) {
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ if (used_virtual_registers[(char)rclass] > last_temporary_register[(char)rclass])
+ last_temporary_register[(char)rclass] = used_virtual_registers[(char)rclass];
+ if (used_virtual_registers[(char)rclass] > 256)
+ used_virtual_registers[(char)rclass] = first_temporary_register[(char)rclass];
+ }
+ }
+}
+
+void close_temp_registers() {
+ char rclass;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ if (used_virtual_registers[(char)rclass] < last_temporary_register[(char)rclass])
+ used_virtual_registers[(char)rclass] = last_temporary_register[(char)rclass];
+ else
+ last_temporary_register[(char)rclass] = used_virtual_registers[(char)rclass];
+ }
+}
+
+int count_scratch_registers() {
+ int rclass;
+ int count;
+
+ count = 0;
+ for (rclass = 0; (char)rclass < RegClassMax; rclass++)
+ count += n_scratch_registers[(char)rclass];
+ return count;
+}
+
+void init_modified_registers() {
+ int i = 0;
+
+ for (i = 0; i < 128; i++)
+ mod_regs_table[i] = NULL;
+}
+
+static void compute_modified_registers(UInt32 *masks) {
+ int rclass;
+ PCodeBlock *block;
+ PCode *pcode;
+ int i;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ masks[(char)rclass] = 0;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ for (i = 0; i < pcode->argCount; i++) {
+ if (pcode->args[i].kind == PCOp_REGISTER && pcode->args[i].data.reg.effect & EffectWrite)
+ masks[pcode->args[i].arg] |= 1 << pcode->args[i].data.reg.reg;
+ }
+ }
+ }
+}
+
+void note_modified_registers(Object *obj) {
+ ModifiedRegisters *mr;
+
+ mr = galloc(sizeof(ModifiedRegisters));
+ mr->obj = obj;
+ compute_modified_registers(mr->mask);
+ mr->next = mod_regs_table[obj->name->hashval];
+ mod_regs_table[obj->name->hashval] = mr;
+}
+
+void find_modified_registers(Object *obj, UInt32 *masks) {
+ char rclass;
+ ModifiedRegisters *scan;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ masks[(char)rclass] = 0xFFFFFFFF;
+
+ if (CParser_HasInternalLinkage(obj)) {
+ for (scan = mod_regs_table[obj->name->hashval]; scan; scan = scan->next) {
+ if (scan->obj == obj)
+ break;
+ }
+ if (scan) {
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ masks[(char)rclass] = scan->mask[(char)rclass];
+ }
+ }
+}
diff --git a/compiler_and_linker/unsorted/StackFrame.c b/compiler_and_linker/unsorted/StackFrame.c
new file mode 100644
index 0000000..5789cb5
--- /dev/null
+++ b/compiler_and_linker/unsorted/StackFrame.c
@@ -0,0 +1,1265 @@
+#include "compiler/StackFrame.h"
+#include "compiler/CError.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/objects.h"
+#include "compiler.h"
+
+#define ALIGN(thing, alignment) ( ~((alignment) - 1) & ((thing) + (alignment) - 1) )
+#define ALIGN_REMAINDER(thing, alignment) ( ALIGN(thing, alignment) - (thing) )
+
+Boolean requires_frame;
+Boolean makes_call;
+Boolean uses_globals;
+Boolean dynamic_stack;
+Boolean large_stack;
+static SInt32 out_param_alignment;
+static SInt32 in_parameter_size;
+static SInt32 in_param_alignment;
+static SInt32 frame_alignment;
+static SInt32 alloca_alignment;
+static SInt32 linkage_area_size;
+static SInt32 parameter_area_size;
+static SInt32 parameter_area_size_estimate;
+static SInt32 local_data_size;
+static SInt32 local_data_limit;
+static SInt32 large_data_near_size;
+static SInt32 large_data_far_size;
+static ObjectList *local_objects[ObjClassMax];
+static ObjectList *local_objects_tail[ObjClassMax];
+static SInt32 non_volatile_save_offset[RegClassMax];
+static SInt32 VRSAVE_save_offset;
+static SInt32 LR_save_offset;
+static SInt32 nonvolatile_save_size;
+static UInt32 vrsave_mask;
+static SInt32 frame_size;
+static SInt32 frame_size_estimate;
+static SInt32 genuine_frame_size;
+static Object *dummylocal;
+static Boolean dynamic_align_stack;
+static Boolean has_varargs;
+static Boolean compressing_data_area;
+static PCode *setup_caller_sp;
+static PCode *align_instr1;
+static PCode *align_instr2;
+static short vrsave_register;
+static PCode *loadvrsave;
+static PCode *storevrsave;
+Object *dummyvaparam;
+void *dummyprofiler;
+
+// forward declarations
+static void insert_local_object(UInt8 oclass, Object *obj);
+static void compress_data_area(void);
+static UInt32 align_bits(UInt32 value, UInt8 bitcount);
+static Boolean use_helper_function(char rclass);
+static Boolean need_link_register(void);
+static void call_helper_function(char *name, char rclass, short effect);
+static void save_nonvolatile_FPRs(int reg, SInt32 offset);
+static void save_nonvolatile_VRs(int reg, SInt32 offset);
+static void restore_nonvolatile_FPRs(int reg, SInt32 offset);
+static void restore_nonvolatile_VRs(int reg, SInt32 offset);
+static void save_nonvolatile_GPRs(int reg, SInt32 offset);
+static void restore_nonvolatile_GPRs(int reg, SInt32 offset);
+static void do_allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size);
+
+void init_stack_globals(void) {
+ char rclass;
+ UInt8 oclass;
+
+ requires_frame = 0;
+ makes_call = 0;
+ uses_globals = 0;
+ dynamic_stack = 0;
+ large_stack = 0;
+ vrsave_register = -1;
+ dynamic_align_stack = 0;
+ compressing_data_area = 0;
+ align_instr1 = NULL;
+ align_instr2 = NULL;
+ setup_caller_sp = NULL;
+ dummyvaparam = NULL;
+ loadvrsave = NULL;
+ storevrsave = NULL;
+ local_data_size = 0;
+ local_data_limit = 0x2000;
+ large_data_near_size = 0;
+ large_data_far_size = 0;
+ frame_size_estimate = 0;
+ in_parameter_size = 0;
+ parameter_area_size = 0;
+ parameter_area_size_estimate = 0;
+ frame_alignment = 8;
+ out_param_alignment = 8;
+ in_param_alignment = 8;
+ alloca_alignment = 0;
+ has_varargs = 0;
+ linkage_area_size = 0;
+ frame_size = 0;
+ genuine_frame_size = 0;
+ nonvolatile_save_size = -1;
+ VRSAVE_save_offset = -1;
+ LR_save_offset = -1;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ non_volatile_save_offset[(char) rclass] = -1;
+
+ dummyprofiler = NULL;
+ dummyvaparam = NULL;
+ dummylocal = NULL;
+
+ for (oclass = 0; oclass < ObjClassMax; oclass++) {
+ local_objects[oclass] = NULL;
+ local_objects_tail[oclass] = NULL;
+ }
+}
+
+void init_frame_sizes(void) {
+ ObjectList *scan;
+ Object *obj;
+ SInt32 r30;
+ SInt32 align;
+ SInt32 mask;
+
+ r30 = in_parameter_size + parameter_area_size_estimate;
+ frame_size_estimate = r30 + 2484;
+ for (scan = locals; scan; scan = scan->next) {
+ obj = scan->object;
+ {
+ align = CMach_AllocationAlignment(obj->type, obj->qual) - 1;
+ mask = ~align;
+ }
+ frame_size_estimate = (frame_size_estimate + align) & mask;
+ frame_size_estimate += obj->type->size;
+ }
+
+ if (frame_size_estimate > 0x8000) {
+ dynamic_stack = 1;
+ large_stack = 1;
+ requires_frame = 1;
+ }
+
+ local_data_limit = 0x8000 - (r30 + 2484);
+
+ if (dynamic_stack) {
+ requires_frame = 1;
+ dummylocal = galloc(sizeof(Object));
+ memclrw(dummylocal, sizeof(Object));
+ dummylocal->type = (Type *) &stvoid;
+ dummylocal->otype = OT_OBJECT;
+ dummylocal->name = GetHashNameNode("<dummy>");
+ dummylocal->datatype = DLOCAL;
+ dummylocal->u.var.info = CodeGen_GetNewVarInfo();
+ dummylocal->u.var.info->flags |= VarInfoFlag80;
+ dummylocal->u.var.info->noregister = 1;
+ }
+
+ if (dynamic_stack) {
+ retain_register(NULL, RegClass_GPR, 31);
+ _FP_ = 31;
+ } else {
+ _FP_ = 1;
+ }
+}
+
+void assign_local_memory(Object *obj) {
+ // some misassigned registers x.x
+ short align;
+ VarInfo *vi;
+
+ align = CMach_AllocationAlignment(obj->type, obj->qual);
+ if (!compressing_data_area && (obj->u.var.info->flags & VarInfoFlag80))
+ return;
+
+ update_frame_align(align);
+ if (local_data_size + (ALIGN_REMAINDER(local_data_size, align) + ALIGN(obj->type->size, align)) < local_data_limit) {
+ local_data_size = ALIGN(local_data_size, align);
+ vi = Registers_GetVarInfo(obj);
+ vi->flags &= ~VarInfoFlag2;
+ vi->flags |= VarInfoFlag80;
+ obj->u.var.uid = local_data_size;
+ local_data_size += ALIGN(obj->type->size, align);
+ insert_local_object(ObjClass0, obj);
+ return;
+ }
+ if (compressing_data_area || obj->type->size <= 32) {
+ large_data_near_size = ALIGN(large_data_near_size, align);
+ vi = Registers_GetVarInfo(obj);
+ vi->flags &= ~VarInfoFlag2;
+ vi->flags |= VarInfoFlag80;
+ obj->u.var.uid = 0x8000 + large_data_near_size;
+ large_data_near_size += ALIGN(obj->type->size, align);
+ insert_local_object(ObjClass1, obj);
+ } else {
+ large_data_far_size = ALIGN(large_data_far_size, align);
+ vi = Registers_GetVarInfo(obj);
+ vi->flags &= ~VarInfoFlag2;
+ vi->flags |= VarInfoFlag80;
+ obj->u.var.uid = 0x10000 + large_data_far_size;
+ large_data_far_size += ALIGN(obj->type->size, align);
+ insert_local_object(ObjClass2, obj);
+ }
+}
+
+void assign_locals_to_memory(ObjectList *first) {
+ ObjectList *list;
+ Object *obj;
+ SInt32 i;
+
+ for (i = 1; i < 1024; i <<= 1) {
+ for (list = first; list; list = list->next) {
+ obj = list->object;
+ if (Registers_GetVarInfo(obj)->used) {
+ if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) {
+ if (obj->type->size <= i)
+ assign_local_memory(obj);
+ }
+ }
+ }
+ }
+
+ for (list = first; list; list = list->next) {
+ obj = list->object;
+ if (Registers_GetVarInfo(obj)->used) {
+ if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) {
+ assign_local_memory(list->object);
+ }
+ }
+
+ if (obj->type && IS_TYPE_ARRAY(obj->type) && IS_TYPE_VECTOR(TYPE_POINTER(obj->type)->target))
+ has_altivec_arrays = 1;
+ }
+}
+
+void compute_frame_sizes(void) {
+ SInt32 altivec_size;
+ SInt32 altivec_offset;
+
+#line 897
+ CError_ASSERT(alloca_alignment == 0 || alloca_alignment == frame_alignment);
+
+ update_asm_nonvolatile_registers();
+ LR_save_offset = 8;
+ non_volatile_save_offset[RegClass_FPR] = -(used_nonvolatile_registers[RegClass_FPR] * 8);
+ non_volatile_save_offset[RegClass_GPR] = -(((15 - non_volatile_save_offset[RegClass_FPR]) & ~15) + used_nonvolatile_registers[RegClass_GPR] * 4);
+ nonvolatile_save_size = -non_volatile_save_offset[RegClass_GPR];
+ non_volatile_save_offset[RegClass_CRFIELD] = 4;
+ VRSAVE_save_offset = -1;
+ non_volatile_save_offset[RegClass_VR] = -1;
+
+ if (copts.altivec_model) {
+ if (vrsave_mask) {
+ VRSAVE_save_offset = non_volatile_save_offset[RegClass_GPR] - 4;
+ nonvolatile_save_size = nonvolatile_save_size + 4;
+ }
+ altivec_size = used_nonvolatile_registers[RegClass_VR] * 16;
+ if (altivec_size > 0)
+ nonvolatile_save_size = ALIGN(nonvolatile_save_size + altivec_size, frame_alignment);
+ }
+
+ if (parameter_area_size)
+ requires_frame = 1;
+
+ compress_data_area();
+ local_data_size = ALIGN(local_data_size, frame_alignment);
+ nonvolatile_save_size = ALIGN(nonvolatile_save_size, frame_alignment);
+ if (!requires_frame && (local_data_size + nonvolatile_save_size) <= 224) {
+#line 1005
+ CError_ASSERT(!dynamic_align_stack);
+ linkage_area_size = 0;
+ frame_size = 0;
+ genuine_frame_size = local_data_size + nonvolatile_save_size;
+ } else {
+ requires_frame = 1;
+ if (parameter_area_size < 32)
+ parameter_area_size = 32;
+ parameter_area_size = ALIGN(parameter_area_size + 24, frame_alignment) - 24;
+ if (large_stack) {
+#line 1019
+ CError_ASSERT(!large_data_far_size);
+ large_data_near_size += parameter_area_size;
+ parameter_area_size = 0;
+ }
+ linkage_area_size = 24;
+ frame_size = nonvolatile_save_size + (altivec_offset = parameter_area_size + 24 + local_data_size);
+ if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR])
+ non_volatile_save_offset[RegClass_VR] = altivec_offset;
+ frame_size += ALIGN_REMAINDER(frame_size, 16);
+ frame_size = ALIGN(frame_size, frame_alignment);
+ genuine_frame_size = frame_size;
+ }
+ if (!large_stack && frame_size > 0x7FFF)
+ CError_ErrorTerm(210);
+}
+
+static void allocate_new_frame(int reg1, int reg2) {
+ if (dynamic_align_stack) {
+#line 1116
+ CError_ASSERT(reg1 != _CALLER_SP_);
+ emitpcode(PC_RLWINM, reg1, 1, 0, align_bits(frame_alignment, 1), 31);
+ if (frame_size > 0x7FFF) {
+#line 1122
+ CError_FATAL();
+ return;
+ }
+
+ if (frame_size)
+ emitpcode(PC_SUBFIC, reg1, reg1, -frame_size);
+ else
+ emitpcode(PC_SUBFIC, reg1, reg1, -genuine_frame_size);
+
+ if (reg2)
+ emitpcode(PC_MR, reg2, 1);
+
+ emitpcode(PC_STWUX, 1, 1, reg1);
+ } else {
+ if (frame_size > 0x7FFF) {
+#line 1153
+ CError_FATAL();
+ } else {
+ emitpcode(PC_STWU, 1, 1, 0, -frame_size);
+ }
+
+ if (reg2)
+ emitpcode(PC_MR, reg2, 1);
+ }
+}
+
+void generate_prologue(PCodeBlock *block) {
+ PCodeBlock *save_block;
+ Boolean needs_lr;
+ Statement *save_statement;
+ Statement stmt;
+ UInt32 vrsave_low;
+ UInt32 vrsave_high;
+
+ save_block = pclastblock;
+ needs_lr = need_link_register();
+ save_statement = current_statement;
+ stmt.sourceoffset = functionbodyoffset;
+ current_statement = &stmt;
+ pclastblock = block;
+
+ if (setup_caller_sp && setup_caller_sp->block) {
+ if (
+ setup_caller_sp->op == PC_MR &&
+ setup_caller_sp->args[1].kind == PCOp_REGISTER &&
+ setup_caller_sp->args[1].arg == RegClass_GPR &&
+ setup_caller_sp->args[1].data.reg.reg == _FP_
+ ) {
+#line 1197
+ CError_FATAL();
+ }
+ _CALLER_SP_ = setup_caller_sp->args[0].data.reg.reg;
+ deletepcode(setup_caller_sp);
+ setup_caller_sp = NULL;
+ } else if (_CALLER_SP_ != _FP_) {
+ _CALLER_SP_ = -1;
+ }
+
+ if (align_instr1 && align_instr1->block) {
+ deletepcode(align_instr1);
+ align_instr1 = NULL;
+ }
+
+ if (align_instr2 && align_instr2->block) {
+ deletepcode(align_instr2);
+ align_instr2 = NULL;
+ }
+
+ if (loadvrsave && loadvrsave->block) {
+ deletepcode(loadvrsave);
+ loadvrsave = NULL;
+ }
+
+ if (storevrsave && storevrsave->block) {
+ deletepcode(storevrsave);
+ storevrsave = NULL;
+ }
+
+ if (needs_lr)
+ emitpcode(PC_MFLR, 0);
+
+ if (used_nonvolatile_registers[RegClass_CRFIELD]) {
+ emitpcode(PC_MFCR, 12);
+ emitpcode(PC_STW, 12, 1, 0, non_volatile_save_offset[RegClass_CRFIELD]);
+ }
+
+ if (used_nonvolatile_registers[RegClass_FPR])
+ save_nonvolatile_FPRs(1, 0);
+ if (used_nonvolatile_registers[RegClass_GPR])
+ save_nonvolatile_GPRs(1, 0);
+ if (needs_lr)
+ emitpcode(PC_STW, 0, 1, 0, 8);
+
+ if (frame_size) {
+ if (vrsave_mask) {
+ emitpcode(PC_MFSPR, 0, 256);
+ emitpcode(PC_STW, 0, 1, 0, VRSAVE_save_offset);
+ vrsave_register = 0;
+ }
+ allocate_new_frame(12, (_CALLER_SP_ > 0 && _CALLER_SP_ != _FP_) ? _CALLER_SP_ : 0);
+ } else {
+#line 1326
+ CError_ASSERT(!dynamic_align_stack);
+ if (vrsave_mask)
+ emitpcode(PC_MFSPR, vrsave_register, 256);
+ }
+
+ if (vrsave_mask) {
+ vrsave_high = vrsave_mask >> 16;
+ vrsave_low = vrsave_mask & 0xFFFF;
+ if (vrsave_mask == 0xFFFFFFFF) {
+ emitpcode(PC_LI, 0, -1);
+ } else {
+ if (vrsave_high)
+ emitpcode(PC_ORIS, 0, vrsave_register, vrsave_high);
+ if (vrsave_low)
+ emitpcode(PC_ORI, 0, 0, vrsave_low);
+ }
+ emitpcode(PC_MTSPR, 256, 0);
+ }
+
+ if (used_nonvolatile_registers[RegClass_VR])
+ save_nonvolatile_VRs(1, 0);
+
+ if (dynamic_stack)
+ emitpcode(PC_MR, 31, 1);
+
+ if (large_stack)
+ do_allocate_dynamic_stack_space(1, 11, 0, large_data_near_size);
+
+ block->flags |= fPCBlockFlag1;
+ pclastblock = save_block;
+ current_statement = save_statement;
+}
+
+void generate_epilogue(PCodeBlock *block, Boolean add_blr) {
+ PCodeBlock *save_block;
+ Boolean needs_lr;
+ Statement *save_statement;
+ Statement stmt;
+
+ save_block = pclastblock;
+ needs_lr = need_link_register();
+ save_statement = current_statement;
+ if (!save_statement) {
+ stmt.sourceoffset = current_linenumber;
+ current_statement = &stmt;
+ }
+ pclastblock = block;
+
+ if (used_nonvolatile_registers[RegClass_VR])
+ restore_nonvolatile_VRs(_FP_, 0);
+
+ if (dynamic_align_stack) {
+ load_store_register(PC_LWZ, 1, 1, NULL, 0);
+ setpcodeflags(fSideEffects);
+ if (needs_lr)
+ load_store_register(PC_LWZ, 0, 1, 0, 8);
+ } else {
+ if (needs_lr)
+ load_store_register(PC_LWZ, 0, _FP_, 0, frame_size + 8);
+ if (frame_size > 0) {
+ if (dynamic_stack) {
+ load_store_register(PC_LWZ, 1, 1, 0, 0);
+ setpcodeflags(fSideEffects);
+ } else {
+ emitpcode(PC_ADDI, 1, 1, 0, frame_size);
+ setpcodeflags(fSideEffects);
+ }
+ }
+ }
+
+ if (used_nonvolatile_registers[RegClass_CRFIELD]) {
+ load_store_register(PC_LWZ, 12, 1, NULL, non_volatile_save_offset[RegClass_CRFIELD]);
+ emitpcode(PC_MTCRF, 255, 12);
+ }
+
+ if (vrsave_mask) {
+ if (!requires_frame) {
+ emitpcode(PC_MTSPR, 256, vrsave_register);
+ } else {
+ emitpcode(PC_LWZ, 11, 1, 0, VRSAVE_save_offset);
+ emitpcode(PC_MTSPR, 256, 11);
+ }
+ }
+
+ if (used_nonvolatile_registers[RegClass_FPR])
+ restore_nonvolatile_FPRs(1, 0);
+ if (needs_lr && !use_helper_function(RegClass_GPR))
+ emitpcode(PC_MTLR, 0);
+
+ if (used_nonvolatile_registers[RegClass_GPR])
+ restore_nonvolatile_GPRs(1, 0);
+ if (needs_lr && use_helper_function(RegClass_GPR))
+ emitpcode(PC_MTLR, 0);
+
+ if (add_blr) {
+ emitpcode(PC_BLR);
+ setpcodeflags(fIsVolatile);
+ }
+
+ block->flags |= fPCBlockFlag2;
+ pclastblock = save_block;
+ current_statement = save_statement;
+}
+
+static void load_base_offset(int dest_reg, int base_reg, SInt32 offset) {
+ if (offset)
+ emitpcode(PC_ADDI, dest_reg, base_reg, 0, offset);
+ else
+ emitpcode(PC_MR, dest_reg, base_reg);
+}
+
+static void save_nonvolatile_FPRs(int reg, SInt32 offset) {
+ short i;
+ SInt32 o;
+
+ o = offset + non_volatile_save_offset[RegClass_FPR];
+
+ if (!use_helper_function(RegClass_FPR)) {
+ for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) {
+ emitpcode(PC_STFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8);
+ setpcodeflags(fIsVolatile);
+ }
+ } else {
+ load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8);
+ call_helper_function("__save_fpr_%d", RegClass_FPR, EffectRead);
+ }
+}
+
+static void save_nonvolatile_VRs(int reg, SInt32 offset) {
+ short i;
+ SInt32 o;
+
+ o = offset + non_volatile_save_offset[RegClass_VR];
+
+ if (!use_helper_function(RegClass_VR)) {
+ for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) {
+ emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16);
+ emitpcode(PC_STVX, 32 - i, reg, 0);
+ setpcodeflags(fIsVolatile);
+ }
+ } else {
+ load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16);
+ call_helper_function("__savev%d", RegClass_VR, EffectRead);
+ }
+}
+
+static void restore_nonvolatile_FPRs(int reg, SInt32 offset) {
+ short i;
+ SInt32 o;
+
+ o = offset + non_volatile_save_offset[RegClass_FPR];
+
+ if (!use_helper_function(RegClass_FPR)) {
+ for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) {
+ load_store_register(PC_LFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8);
+ setpcodeflags(fIsVolatile);
+ }
+ } else {
+ load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8);
+ call_helper_function("__restore_fpr_%d", RegClass_FPR, EffectWrite);
+ }
+}
+
+static void restore_nonvolatile_VRs(int reg, SInt32 offset) {
+ short i;
+ SInt32 o;
+
+ o = offset + non_volatile_save_offset[RegClass_VR];
+
+ if (!use_helper_function(RegClass_VR)) {
+ for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) {
+ emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16);
+ setpcodeflags(fIsVolatile);
+ emitpcode(PC_LVX, 32 - i, reg, 0);
+ setpcodeflags(fIsVolatile);
+ }
+ } else {
+ load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16);
+ call_helper_function("__restv%d", RegClass_VR, EffectWrite);
+ }
+}
+
+static void save_nonvolatile_GPRs(int reg, SInt32 offset) {
+ int i;
+ SInt32 o;
+
+ o = offset + non_volatile_save_offset[RegClass_GPR];
+
+ if (!use_helper_function(RegClass_GPR)) {
+ if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimize_for_size && (used_nonvolatile_registers[RegClass_GPR] > 1)))) {
+ emitpcode(PC_STMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o);
+ } else {
+ for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) {
+ emitpcode(PC_STW, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4);
+ }
+ }
+ } else {
+ load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4);
+ call_helper_function("__savegpr_%d", RegClass_GPR, EffectRead);
+ }
+}
+
+static void restore_nonvolatile_GPRs(int reg, SInt32 offset) {
+ int i;
+ SInt32 o;
+
+ o = offset + non_volatile_save_offset[RegClass_GPR];
+
+ if (!use_helper_function(RegClass_GPR)) {
+ if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimize_for_size && (used_nonvolatile_registers[RegClass_GPR] > 1)))) {
+ emitpcode(PC_LMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o);
+ setpcodeflags(fIsVolatile);
+ } else {
+ for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) {
+ emitpcode(PC_LWZ, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4);
+ setpcodeflags(fIsVolatile);
+ }
+ }
+ } else {
+ load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4);
+ call_helper_function("__restgpr_%d", RegClass_GPR, EffectWrite);
+ }
+}
+
+static void do_allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size) {
+ load_store_register(PC_LWZ, reg2, 1, NULL, 0);
+ if (flag1) {
+ size = ALIGN(size, frame_alignment);
+ if (size < 0x8000) {
+ emitpcode(PC_STWU, reg2, 1, 0, -size);
+ } else {
+ emitpcode(PC_LIS, reg1, 0, (short) HIGH_PART(-size));
+ if (-size)
+ emitpcode(PC_ADDI, reg1, reg1, 0, LOW_PART(-size));
+ emitpcode(PC_STWUX, reg2, 1, reg1);
+ setpcodeflags(fIsVolatile | fSideEffects);
+ }
+ } else {
+ emitpcode(PC_STWUX, reg2, 1, reg1);
+ setpcodeflags(fIsVolatile | fSideEffects);
+ }
+}
+
+void allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size) {
+ if (copts.altivec_model)
+ update_frame_align(16);
+ do_allocate_dynamic_stack_space(flag1, reg1, reg2, size);
+ add_immediate(reg1, 1, dummylocal, 0);
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct Traceback {
+ UInt8 x0;
+ UInt8 x1;
+ UInt8 x2;
+ UInt8 x3;
+ UInt8 x4;
+ UInt8 x5;
+
+ UInt8 x6_0 : 2;
+ UInt8 x6_1 : 1; // set to 1
+ UInt8 x6_2 : 5;
+
+ UInt8 x7_0 : 1;
+ UInt8 x7_1 : 1; // set to 1
+ UInt8 has_dynamic_stack : 1; // set to 1 if dynamic_stack
+ UInt8 x7_3 : 3;
+ UInt8 uses_CRs : 1; // set to 1 if CRs used
+ UInt8 needs_link_register : 1; // set to 1 if link register used
+
+ UInt8 has_frame_size : 1; // set to 1 if frame_size is nonzero
+ UInt8 x8_1 : 1; // set to 0
+ UInt8 used_FPRs : 6; // stores non-volatile FPRs used
+
+ UInt8 x9_0 : 1; // set to 0
+ UInt8 x9_1 : 1; // set to 1 if VRs or vrsave used
+ UInt8 used_GPRs : 6; // stores non-volatile GPRs used
+
+ UInt8 xA;
+ UInt8 xB;
+
+ SInt32 funcsize;
+ SInt16 namelen;
+ char name[0];
+} Traceback;
+
+typedef struct TracebackExtra {
+ UInt8 used_VRs : 6;
+ UInt8 has_vrsave_mask : 1;
+ UInt8 is_varargs : 1;
+ UInt8 vec_arg_count : 7;
+ UInt8 has_vrsave_mask_or_used_VRs : 1;
+} TracebackExtra;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+char *generate_traceback(SInt32 funcsize, char *funcname, SInt32 *tbsize, Object *func) {
+ char *work;
+ short namelen;
+ Traceback *buf;
+ SInt32 bufsize;
+
+ namelen = strlen(funcname);
+ bufsize = ALIGN(sizeof(Traceback) + namelen + (dynamic_stack ? 1 : 0) + ((used_nonvolatile_registers[RegClass_VR] || vrsave_mask) ? sizeof(TracebackExtra) : 0), 4);
+ buf = lalloc(bufsize);
+ memclrw(buf, bufsize);
+
+ buf->x4 = 0;
+ buf->x5 = copts.cplusplus ? 9 : 0;
+ buf->x6_1 = 1;
+ buf->x7_1 = 1;
+ if (dynamic_stack)
+ buf->has_dynamic_stack = 1;
+ if (used_nonvolatile_registers[RegClass_CRFIELD])
+ buf->uses_CRs = 1;
+ if (need_link_register())
+ buf->needs_link_register = 1;
+ if (frame_size)
+ buf->has_frame_size = 1;
+ buf->used_FPRs = used_nonvolatile_registers[RegClass_FPR];
+ buf->used_GPRs = used_nonvolatile_registers[RegClass_GPR];
+ buf->x8_1 = 0;
+ buf->x9_0 = 0;
+ buf->x9_1 = (used_nonvolatile_registers[RegClass_VR] || vrsave_mask) != 0;
+ buf->funcsize = funcsize;
+ buf->namelen = namelen;
+
+ work = buf->name;
+ strcpy(work, funcname);
+ work += namelen;
+ if (dynamic_stack) {
+ *(work++) = 31;
+ }
+
+ if (vrsave_mask || used_nonvolatile_registers[RegClass_VR]) {
+ TracebackExtra *extra;
+ Boolean is_varargs;
+ int vec_count;
+ FuncArg *args, *scan;
+ Type *type;
+
+ extra = (TracebackExtra *) work;
+ vec_count = 0;
+ args = TYPE_FUNC(func->type)->args;
+ scan = args;
+ while (scan && scan != &elipsis)
+ scan = scan->next;
+ is_varargs = scan == &elipsis;
+ while (args) {
+ if ((type = args->type) && IS_TYPE_VECTOR(type))
+ vec_count++;
+ args = args->next;
+ }
+ extra->used_VRs = used_nonvolatile_registers[RegClass_VR];
+ extra->has_vrsave_mask = vrsave_mask != 0;
+ extra->is_varargs = is_varargs;
+ extra->vec_arg_count = vec_count;
+ extra->has_vrsave_mask_or_used_VRs = vrsave_mask || used_nonvolatile_registers[RegClass_VR];
+ }
+
+ *tbsize = bufsize;
+ return (char *) buf;
+}
+
+static SInt32 localsbase(void) {
+ SInt32 size = parameter_area_size;
+ if (frame_size || dynamic_align_stack)
+ size += linkage_area_size;
+ else
+ size -= genuine_frame_size;
+ return size;
+}
+
+static SInt32 parametersbase(int flag) {
+ if (flag)
+ return 24;
+
+ return frame_size ? (genuine_frame_size + 24) : 24;
+}
+
+void check_dynamic_aligned_frame(void) {
+ PCode *pc;
+
+ if (used_nonvolatile_registers[RegClass_VR]) {
+ update_frame_align(16);
+ requires_frame = 1;
+ }
+
+ if (frame_alignment > in_param_alignment) {
+ dynamic_align_stack = 1;
+ requires_frame = 1;
+#line 2091
+ CError_ASSERT(!has_varargs || _CALLER_SP_ != -1);
+#line 2096
+ CError_ASSERT(_CALLER_SP_ != _FP_);
+ if (setup_caller_sp && setup_caller_sp->block) {
+ align_instr1 = makepcode(PC_RLWINM, 12, 1, 0, 5, 31);
+ insertpcodebefore(setup_caller_sp, align_instr1);
+ align_instr2 = makepcode(PC_STWUX, 1, 1, 12);
+ insertpcodeafter(setup_caller_sp, align_instr2);
+ }
+ } else {
+ dynamic_align_stack = 0;
+ if (setup_caller_sp && setup_caller_sp->block) {
+ pc = makepcode(PC_MR, _CALLER_SP_, _FP_);
+ insertpcodebefore(setup_caller_sp, pc);
+ deletepcode(setup_caller_sp);
+ setup_caller_sp = pc;
+ }
+ _CALLER_SP_ = _FP_;
+ }
+
+ vrsave_mask = 0;
+ if (copts.altivec_model) {
+ vrsave_mask = colored_vrs_as_vrsave(pcbasicblocks);
+ if (!requires_frame && vrsave_mask) {
+ vrsave_register = 11;
+ loadvrsave = makepcode(PC_LWZ, 11, 1, 0, -4);
+ appendpcode(prologue, loadvrsave);
+ storevrsave = makepcode(PC_STW, 11, 1, 0, -4);
+ appendpcode(epilogue, storevrsave);
+ }
+ }
+}
+
+void move_varargs_to_memory(void) {
+ short reg;
+
+ has_varargs = 1;
+ dummyvaparam = galloc(sizeof(Object));
+ memclrw(dummyvaparam, sizeof(Object));
+
+ dummyvaparam->type = (Type *) &stvoid;
+ dummyvaparam->otype = OT_OBJECT;
+ dummyvaparam->name = GetHashNameNode("<vaparam>");
+ dummyvaparam->datatype = DLOCAL;
+ dummyvaparam->u.var.info = CodeGen_GetNewVarInfo();
+ dummyvaparam->u.var.uid = 0;
+ dummyvaparam->u.var.info->noregister = 1;
+ Registers_GetVarInfo(dummyvaparam)->flags = (Registers_GetVarInfo(dummyvaparam)->flags & ~VarInfoFlag1) | VarInfoFlag1;
+
+ for (reg = last_argument_register[RegClass_GPR] + 1; (int)reg <= 10; reg++) {
+ emitpcode(PC_STW, reg, local_base_register(dummyvaparam), dummyvaparam, (reg - 3) * 4);
+ setpcodeflags(fPCodeFlag20 | fPCodeFlag8000);
+ }
+}
+
+void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVarargs) {
+ // almost matches except for the not/andc issue
+ SInt32 pos;
+ ObjectList *list;
+ Object *obj;
+ Type *type;
+ short reg;
+ SInt32 chk;
+ Boolean flag;
+
+ pos = 0;
+ reg = 2;
+
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ type = obj->type;
+ if (!IS_TYPE_VECTOR(type)) {
+ obj->datatype = DLOCAL;
+ obj->u.var.info = CodeGen_GetNewVarInfo();
+ if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) ||
+ IS_TYPE_12BYTES_MEMBERPOINTER(type)) {
+ chk = CMach_ArgumentAlignment(type);
+ if (chk > 4) {
+ pos = ALIGN(pos, chk);
+ update_in_param_align(chk);
+ }
+ }
+ obj->u.var.uid = pos;
+ Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1;
+ if (!copts.little_endian && (IS_TYPE_INT(obj->type) || IS_TYPE_ENUM(obj->type)) && obj->type->size < 4)
+ obj->u.var.uid += 4 - obj->type->size;
+ pos += type->size;
+ pos = ALIGN(pos, 4);
+ } else {
+ obj->u.var.info = CodeGen_GetNewVarInfo();
+ obj->u.var.uid = 0;
+ obj->datatype = DLOCAL;
+ flag = 1;
+ if (reg <= 13)
+ flag = hasVarargs;
+ if (flag) {
+ pos = ALIGN(pos + 24, 16) - 24;
+ obj->u.var.offset = pos;
+ pos += 16;
+ update_in_param_align(16);
+ Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1;
+ } else {
+ assign_local_memory(obj);
+ Registers_GetVarInfo(obj)->flags = Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1;
+ }
+ reg++;
+ }
+ }
+
+ in_parameter_size = (in_parameter_size < pos) ? pos : in_parameter_size;
+#line 2408
+ CError_ASSERT(!dummyvaparam);
+}
+
+SInt32 set_out_param_displ(SInt32 a, Type *type, Boolean flag, SInt32 *outvar, SInt32 b) {
+ // does not match due to errant andc
+ SInt32 argAlign;
+
+ if (!flag && !b) {
+ *outvar = 0;
+ return a;
+ }
+
+ if (IS_TYPE_VECTOR(type)) {
+ update_out_param_align(16);
+ a = ALIGN(a + 16 + 24, 16) - 24;
+ } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || IS_TYPE_12BYTES_MEMBERPOINTER(type)) {
+ argAlign = CMach_ArgumentAlignment(type);
+ if (argAlign > 4) {
+ a = ALIGN(a + 24, argAlign) - 24;
+ update_in_param_align(argAlign);
+ }
+ }
+
+ *outvar = a;
+ a = ALIGN(a + b, 4);
+ return a;
+}
+
+SInt32 out_param_displ_to_offset(SInt32 displ) {
+ return displ + 24;
+}
+
+Boolean needs_frame(void) {
+ return (frame_size > 224) || requires_frame;
+}
+
+void update_out_param_size(SInt32 size) {
+ if (size < 32)
+ size = 32;
+ if (parameter_area_size < size)
+ parameter_area_size = size;
+}
+
+void estimate_out_param_size(SInt32 size) {
+ if (parameter_area_size_estimate < size)
+ parameter_area_size_estimate = size;
+}
+
+void update_out_param_align(SInt32 align) {
+ if (out_param_alignment < align)
+ out_param_alignment = align;
+ update_frame_align(align);
+}
+
+void update_in_param_align(SInt32 align) {
+ if (in_param_alignment < align)
+ in_param_alignment = align;
+}
+
+void update_frame_align(SInt32 align) {
+ if (frame_alignment < align)
+ frame_alignment = align;
+}
+
+SInt32 local_offset_32(Object *obj) {
+ short align;
+ SInt32 offset;
+
+ if (obj->u.var.info->flags & VarInfoFlag1)
+ align = CMach_ArgumentAlignment(obj->type);
+ else
+ align = CMach_AllocationAlignment(obj->type, obj->qual);
+
+ offset = obj->u.var.uid;
+ if (offset > 0x7FFF)
+ offset = 0x8000 - offset - ALIGN(obj->type->size, align);
+
+ if (obj->u.var.info->flags & VarInfoFlag1)
+ return offset + parametersbase(local_base_register(obj) != _FP_);
+ else
+ return offset + localsbase();
+}
+
+SInt16 local_offset_lo(Object *obj, SInt32 offset) {
+ SInt32 combo = offset + local_offset_32(obj);
+ return LOW_PART(combo);
+ //return (SInt16) (offset + local_offset_32(obj));
+}
+
+SInt16 local_offset_ha(Object *obj, SInt32 offset) {
+ SInt32 combo = offset + local_offset_32(obj);
+ return HIGH_PART(combo);
+ //return (SInt16) ((combo >> 16) + ((combo & 0x8000) >> 15));
+}
+
+SInt16 local_offset_16(Object *obj) {
+ SInt32 offset32 = local_offset_32(obj);
+ SInt16 offset16 = (SInt16) offset32;
+#line 2662
+ CError_ASSERT(offset32 == offset16);
+ return offset16;
+}
+
+Boolean local_is_16bit_offset(Object *obj) {
+ SInt32 offset32 = local_offset_32(obj);
+ SInt16 offset16 = (SInt16) offset32;
+ return offset32 == offset16;
+}
+
+int local_base_register(Object *obj) {
+ PCode *pc;
+
+ if (obj->u.var.info->flags & VarInfoFlag1) {
+ if (coloring && _CALLER_SP_ == -1) {
+ _CALLER_SP_ = used_virtual_registers[RegClass_GPR]++;
+ pc = makepcode(PC_LWZ, _CALLER_SP_, 1, 0, 0);
+ setup_caller_sp = pc;
+ appendpcode(prologue, pc);
+ }
+ return _CALLER_SP_;
+ } else {
+ return _FP_;
+ }
+}
+
+static UInt32 align_bits(UInt32 value, UInt8 bitcount) {
+ UInt32 base = bitcount != 0;
+ switch (value) {
+ case 0x0002: return base + 30;
+ case 0x0004: return base + 29;
+ case 0x0008: return base + 28;
+ case 0x0010: return base + 27;
+ case 0x0020: return base + 26;
+ case 0x0040: return base + 25;
+ case 0x0080: return base + 24;
+ case 0x0100: return base + 23;
+ case 0x0200: return base + 22;
+ case 0x0400: return base + 21;
+ case 0x0800: return base + 20;
+ case 0x1000: return base + 19;
+ case 0x2000: return base + 18;
+ default:
+ #line 2754
+ CError_FATAL();
+ return base + 27;
+ }
+}
+
+Boolean is_large_frame(void) {
+#line 2769
+ CError_ASSERT(frame_size != -1);
+ return large_stack;
+}
+
+void no_frame_for_asm(void) {
+ frame_size = 0;
+}
+
+Boolean can_add_displ_to_local(Object *obj, SInt32 displ) {
+ if (obj->datatype != DLOCAL)
+ return 0;
+
+ if (local_offset_32(obj) == (short) local_offset_32(obj))
+ if ((displ + local_offset_32(obj)) == (short) (displ + local_offset_32(obj)))
+ return 1;
+
+ return 0;
+}
+
+SInt32 get_alloca_alignment(void) {
+ SInt32 align = frame_alignment;
+ if (copts.altivec_model)
+ align = ALIGN(align, 16);
+
+ if (!alloca_alignment) {
+ alloca_alignment = align;
+ } else {
+#line 2825
+ CError_ASSERT(alloca_alignment == align);
+ }
+
+ return align_bits(align, 0);
+}
+
+static Boolean use_helper_function(char rclass) {
+ if (copts.no_register_save_helpers)
+ return 0;
+
+ switch (rclass) {
+ case RegClass_GPR:
+ if (copts.use_lmw_stmw)
+ return 0;
+ return (used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimize_for_size && used_nonvolatile_registers[RegClass_GPR] > 2);
+ case RegClass_FPR:
+ return (used_nonvolatile_registers[RegClass_FPR] > 3) || (copts.optimize_for_size && used_nonvolatile_registers[RegClass_FPR] > 2);
+ case RegClass_VR:
+ return (used_nonvolatile_registers[RegClass_VR] > 3) || (copts.optimize_for_size && used_nonvolatile_registers[RegClass_VR] > 2);
+ default:
+#line 2862
+ CError_FATAL();
+ return 0;
+ }
+}
+
+static Boolean need_link_register(void) {
+ if (copts.codegen_pic && uses_globals)
+ return 1;
+
+ if (makes_call)
+ return 1;
+
+ return use_helper_function(RegClass_FPR) || use_helper_function(RegClass_GPR) || use_helper_function(RegClass_VR);
+}
+
+static void call_helper_function(char *name, char rclass, short effect) {
+ char str[32];
+ Object *func;
+ NameSpace *save_scope;
+ PCode *pc;
+ int extra_args;
+ PCodeArg *arg;
+ short i;
+
+ extra_args = 1;
+ if (rclass == RegClass_VR)
+ extra_args = 2;
+
+ sprintf(str, name, 32 - used_nonvolatile_registers[rclass]);
+
+ save_scope = cscope_current;
+ cscope_current = cscope_root;
+ func = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ cscope_current = save_scope;
+
+ func->name = GetHashNameNodeExport(str);
+
+ pc = makepcode(PC_BL, extra_args + used_nonvolatile_registers[rclass], func, 0);
+ for (i = 1, arg = &pc->args[1]; i <= used_nonvolatile_registers[rclass]; i++, arg++) {
+ arg->kind = PCOp_REGISTER;
+ arg->arg = rclass;
+ arg->data.reg.reg = n_real_registers[rclass] - i;
+ arg->data.reg.effect = effect;
+ }
+
+ if (rclass == RegClass_VR) {
+ arg[1].kind = PCOp_REGISTER;
+ arg[1].arg = RegClass_GPR;
+ arg[1].data.reg.reg = 12;
+ arg[1].data.reg.effect = EffectWrite;
+ arg[2].kind = PCOp_REGISTER;
+ arg[2].arg = RegClass_GPR;
+ arg[2].data.reg.reg = 0;
+ arg[2].data.reg.effect = EffectRead;
+ } else {
+ arg[1].kind = PCOp_REGISTER;
+ arg[1].arg = RegClass_GPR;
+ arg[1].data.reg.reg = 11;
+ arg[1].data.reg.effect = EffectRead;
+ }
+
+ appendpcode(pclastblock, pc);
+ setpcodeflags(fSideEffects);
+}
+
+static SInt32 nearest_power_of_two(SInt32 n) {
+ SInt32 power = 1;
+ do {
+ power <<= 1;
+ } while (power && power < n);
+
+#line 2933
+ CError_ASSERT(power != 0);
+ return power;
+}
+
+static void compress_data_area(void) {
+ // doesn't quite match
+ SInt32 r0;
+ SInt32 r7;
+ ObjectList *list;
+ Object *obj;
+ PCodeBlock *block;
+ PCode *pc;
+ int i;
+
+ compressing_data_area = 1;
+
+ if (large_stack) {
+ r0 = 0;
+ } else {
+ r0 = parameter_area_size;
+ if (r0 < 32)
+ r0 = 32;
+ }
+ r7 = ALIGN(r0 + 24, frame_alignment) - 24;
+ local_data_limit = 0x8000 - ALIGN(24 + in_parameter_size + nonvolatile_save_size + r7, frame_alignment);
+
+ if (local_objects_tail[ObjClass0]) {
+ if (local_objects[ObjClass1]) {
+ local_objects_tail[ObjClass0]->next = local_objects[ObjClass1];
+ local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1];
+ }
+ if (local_objects[ObjClass2]) {
+ local_objects_tail[ObjClass0]->next = local_objects[ObjClass2];
+ local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2];
+ }
+ } else if (local_objects_tail[ObjClass1]) {
+ local_objects[ObjClass0] = local_objects[ObjClass1];
+ local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1];
+ if (local_objects[ObjClass2]) {
+ local_objects_tail[ObjClass0]->next = local_objects[ObjClass2];
+ local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2];
+ }
+ } else {
+ local_objects[ObjClass0] = local_objects[ObjClass2];
+ local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2];
+ }
+
+ for (list = local_objects[ObjClass0]; list; list = list->next)
+ Registers_GetVarInfo(list->object)->used = 0;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (pc = block->firstPCode; pc; pc = pc->nextPCode) {
+ for (i = 0; i < pc->argCount; i++) {
+ if (pc->args[i].kind == PCOp_MEMORY && pc->args[i].data.mem.obj && pc->args[i].data.mem.obj->datatype == DLOCAL)
+ Registers_GetVarInfo(pc->args[i].data.mem.obj)->used = 1;
+ }
+ }
+ }
+
+ local_data_size = 0;
+ large_data_near_size = 0;
+ large_data_far_size = 0;
+
+ for (list = local_objects[ObjClass0]; list; list = list->next) {
+ obj = list->object;
+ if (Registers_GetVarInfo(obj)->used)
+ assign_local_memory(obj);
+ }
+}
+
+static void insert_local_object(UInt8 oclass, Object *obj) {
+ ObjectList *list;
+
+ if (!compressing_data_area) {
+ list = lalloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = obj;
+ if (!local_objects[oclass])
+ local_objects[oclass] = list;
+ if (local_objects_tail[oclass])
+ local_objects_tail[oclass]->next = list;
+ local_objects_tail[oclass] = list;
+ }
+}
diff --git a/compiler_and_linker/unsorted/TOC.c b/compiler_and_linker/unsorted/TOC.c
new file mode 100644
index 0000000..65dc39b
--- /dev/null
+++ b/compiler_and_linker/unsorted/TOC.c
@@ -0,0 +1,2041 @@
+#include "cos.h"
+#include "compiler/TOC.h"
+#include "compiler/CError.h"
+#include "compiler/CInt64.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+#include "compiler.h"
+
+ObjectList *toclist;
+ObjectList *exceptionlist;
+void *descriptorlist;
+void *floatconstpool;
+void *doubleconstpool;
+ObjectList *floatconstlist;
+void *vectorconstpool;
+ObjectList *vectorconstlist;
+Object toc0;
+Boolean no_descriptors;
+Object pic_base;
+VarInfo pic_base_varinfo;
+short pic_base_reg;
+CodeLabelList *codelabellist;
+
+UInt8 lvslBytes[16][16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E
+};
+
+UInt8 lvsrBytes[16][16] = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
+};
+
+// forward decls
+static void estimate_func_param_size(ENode *node);
+
+static int disables_optimizer(ENode *node) {
+ ENode *funcref = node->data.funccall.funcref;
+ if (ENODE_IS(funcref, EOBJREF)) {
+ if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___setjmp"))
+ return 1;
+ if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___vec_setjmp"))
+ return 1;
+ }
+ return 0;
+}
+
+void setupaddressing(void) {
+ floatconstlist = NULL;
+ descriptorlist = NULL;
+ toclist = NULL;
+ exceptionlist = NULL;
+ vectorconstlist = NULL;
+ vectorconstpool = NULL;
+ floatconstpool = NULL;
+ doubleconstpool = NULL;
+
+ no_descriptors = 1;
+ memclrw(&toc0, sizeof(toc0));
+
+ pic_base_reg = 0;
+ memclrw(&pic_base, sizeof(pic_base));
+ memclrw(&pic_base_varinfo, sizeof(pic_base_varinfo));
+ pic_base.otype = OT_OBJECT;
+ pic_base.type = (Type *) &void_ptr;
+ pic_base.datatype = DNONLAZYPTR;
+ pic_base.u.toc.info = &pic_base_varinfo;
+}
+
+void createNonLazyPointer(Object *obj) {
+ Object *toc;
+ ObjectList *list;
+
+ toc = galloc(sizeof(Object));
+ obj->toc = toc;
+ memclrw(toc, sizeof(Object));
+
+ toc->otype = OT_OBJECT;
+ toc->name = CParser_GetUniqueName();
+ toc->toc = NULL;
+ toc->section = SECT_NONLAZY_PTRS;
+ toc->u.toc.info = CodeGen_GetNewVarInfo();
+ toc->sclass = OBJECT_SCLASS_102;
+ toc->qual = Q_CONST;
+ toc->datatype = DNONLAZYPTR;
+ toc->flags |= OBJECT_FLAGS_2;
+ toc->type = CDecl_NewPointerType(obj->type);
+ toc->u.toc.over_load = obj;
+ toc->u.toc.linkname = CMangler_GetLinkName(obj);
+
+ list = galloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = toc;
+ list->next = toclist;
+ toclist = list;
+}
+
+void referenceIndirectPointer(Object *obj) {
+ VarInfo *vi = obj->toc->u.toc.info;
+ vi->used = 1;
+ vi->usage += copts.optimize_for_size ? 1 : curstmtvalue;
+}
+
+Object *createIndirect(Object *obj, Boolean flag1, Boolean flag2) {
+#line 622
+ CError_ASSERT(!copts.no_common || (obj->section != SECT_COMMON_VARS) || (obj->qual & Q_20000));
+
+ if (CParser_HasInternalLinkage(obj))
+ return NULL;
+ if (ObjGen_IsExported(obj))
+ return NULL;
+
+ if (!copts.no_common && obj->datatype == DDATA && obj->section == SECT_DEFAULT && (obj->qual & Q_1000000))
+ obj->section = SECT_COMMON_VARS;
+
+ if (copts.codegen_dynamic && (!copts.no_common || !(obj->qual & Q_1000000))) {
+ if (!obj->toc)
+ createNonLazyPointer(obj);
+ else if (flag1)
+ obj->toc->u.toc.info = CodeGen_GetNewVarInfo();
+
+ if (flag2)
+ referenceIndirectPointer(obj);
+
+ return obj->toc;
+ } else {
+ return NULL;
+ }
+}
+
+Object *createfloatconstant(Type *type, Float *data) {
+ ObjectList *list;
+ Object *obj;
+ UInt32 *check;
+
+ for (list = floatconstlist; list; list = list->next) {
+ obj = list->object;
+ check = (UInt32 *) obj->u.data.u.floatconst;
+ if (obj->type == type && check[0] == ((UInt32 *) data)[0] && check[1] == ((UInt32 *) data)[1])
+ return obj;
+ }
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = type;
+ obj->name = CParser_GetUniqueName();
+ obj->toc = NULL;
+ obj->u.data.info = NULL;
+ obj->u.data.linkname = obj->name;
+ obj->sclass = OBJECT_SCLASS_102;
+ obj->qual = Q_CONST | Q_10000;
+ obj->datatype = DDATA;
+ if (type->size == 8) {
+ obj->section = SECT_8BYTE_LITERALS;
+ } else if (type->size == 4) {
+ obj->section = SECT_4BYTE_LITERALS;
+ } else {
+#line 807
+ CError_FATAL();
+ }
+
+ obj->flags |= OBJECT_FLAGS_2;
+
+ obj->u.data.u.floatconst = galloc(sizeof(Float));
+ *obj->u.data.u.floatconst = *data;
+
+ list = galloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = obj;
+ list->next = floatconstlist;
+ floatconstlist = list;
+
+ ObjGen_DeclareFloatConst(obj);
+ return obj;
+}
+
+Object *createvectorconstant(Type *type, MWVector128 *data) {
+ ObjectList *list;
+ Object *obj;
+ MWVector128 *check;
+
+ for (list = vectorconstlist; list; list = list->next) {
+ obj = list->object;
+ check = obj->u.data.u.vector128const;
+ if (check->ul[0] == data->ul[0] && check->ul[1] == data->ul[1] && check->ul[2] == data->ul[2] && check->ul[3] == data->ul[3])
+ return obj;
+ }
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = type;
+ obj->name = CParser_GetUniqueName();
+ obj->toc = NULL;
+ obj->u.data.info = NULL;
+ obj->u.data.linkname = obj->name;
+ obj->sclass = OBJECT_SCLASS_102;
+ obj->qual = Q_CONST | Q_10000;
+ obj->datatype = DDATA;
+ if (type->size == 16) {
+ obj->section = SECT_16BYTE_LITERALS;
+ } else {
+#line 900
+ CError_FATAL();
+ }
+
+ obj->flags |= OBJECT_FLAGS_2;
+
+ obj->u.data.u.vector128const = galloc(sizeof(MWVector128));
+ *obj->u.data.u.vector128const = *data;
+
+ list = galloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = obj;
+ list->next = vectorconstlist;
+ vectorconstlist = list;
+
+ ObjGen_DeclareVectorConst(obj);
+ return obj;
+}
+
+void DeclarePooledConstants() {
+ // TODO CInit
+}
+
+static Object *CreatePooledFloatConst(Type *type, Float *data, SInt32 *unkptr) {
+ // TODO CDecl
+}
+
+Object *CreateFloatConst(Type *type, Float *data, SInt32 *unkptr) {
+ *unkptr = 0;
+ return createfloatconstant(type, data);
+}
+
+static void RewriteFloatConst(ENode *expr) {
+ Object *obj;
+ SInt32 n;
+ ENode *subexpr;
+
+ obj = CreateFloatConst(expr->rtype, &expr->data.floatval, &n);
+ if (n) {
+ subexpr = makediadicnode(create_objectrefnode(obj), intconstnode(&stunsignedlong, n), EADD);
+ } else {
+ subexpr = create_objectrefnode(obj);
+ }
+
+ expr->type = EINDIRECT;
+ expr->cost = 1;
+ expr->flags |= Q_CONST;
+ expr->data.monadic = subexpr;
+}
+
+static void RewriteVectorConst(ENode *expr) {
+ UInt8 data[16];
+ // TODO
+}
+
+static Object *createcodelabel(CLabel *label) {
+ CodeLabelList *list;
+ Object *obj;
+
+ for (list = codelabellist; list; list = list->next) {
+ if (list->label == label)
+ return list->object;
+ }
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = (Type *) &void_ptr;
+ obj->name = label->uniquename;
+ obj->toc = NULL;
+ obj->u.data.info = NULL; // not sure if this is the right union!
+ obj->sclass = OBJECT_SCLASS_102;
+ obj->qual = Q_CONST;
+ obj->datatype = DDATA;
+ obj->flags |= OBJECT_FLAGS_2 | OBJECT_FLAGS_4;
+
+ list = galloc(sizeof(CodeLabelList));
+ memclrw(list, sizeof(CodeLabelList));
+ list->object = obj;
+ list->label = label;
+ list->next = codelabellist;
+ codelabellist = list;
+
+ return obj;
+}
+
+void dumpcodelabels(Object *func) {
+ CodeLabelList *list;
+
+ for (list = codelabellist; list; list = list->next)
+ ObjGen_DeclareCodeLabel(list->object, list->label->pclabel->block->codeOffset, func);
+}
+
+static void referenceexception(Object *obj) {
+ ObjectList *list;
+
+ if (obj && obj->otype == OT_OBJECT && obj->datatype == DLOCAL) {
+ for (list = exceptionlist; list; list = list->next) {
+ if (list->object == obj)
+ return;
+ }
+
+ list = lalloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = obj;
+ list->next = exceptionlist;
+ exceptionlist = list;
+ }
+}
+
+static ENodeType invert_relop(ENodeType nodetype) {
+ switch (nodetype) {
+ case ELESS: return EGREATEREQU;
+ case EGREATER: return ELESSEQU;
+ case ELESSEQU: return EGREATER;
+ case EGREATEREQU: return ELESS;
+ case EEQU: return ENOTEQU;
+ case ENOTEQU: return EEQU;
+ default: return nodetype;
+ }
+}
+
+static ENode *COND_to_COMPARE(ENode *cond, ENode *expr1, ENode *expr2) {
+ SInt32 val1;
+ SInt32 val2;
+ SInt32 condval;
+ ENodeType invop;
+
+ while (expr1->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr1->rtype))
+ expr1 = expr1->data.monadic;
+ while (expr2->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr2->rtype))
+ expr2 = expr2->data.monadic;
+
+ if (expr1->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr1->rtype) || !CInt64_IsInRange(expr1->data.intval, 4))
+ return NULL;
+ if (expr2->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr2->rtype) || !CInt64_IsInRange(expr2->data.intval, 4))
+ return NULL;
+
+ val1 = expr1->data.intval.lo;
+ val2 = expr2->data.intval.lo;
+ condval = 0;
+ switch (val1) {
+ case 1:
+ if (val2 != 0)
+ return NULL;
+ break;
+ case 0:
+ condval = 1;
+ if (val2 != 1)
+ return NULL;
+ break;
+ default:
+ return NULL;
+ }
+
+ while (cond->type == ELOGNOT) {
+ condval = (condval + 1) & 1;
+ cond = cond->data.monadic;
+ }
+
+ if (condval) {
+ invop = invert_relop(cond->type);
+ if (invop == cond->type)
+ return NULL;
+ cond->type = invop;
+ }
+
+ return cond;
+}
+
+static ENode *comparewithzero(ENode *expr) {
+ ENode *expr1;
+ ENode *expr2;
+ ENode *tmp;
+
+ expr1 = lalloc(sizeof(ENode));
+ memclrw(expr1, sizeof(ENode));
+ expr2 = lalloc(sizeof(ENode));
+ memclrw(expr2, sizeof(ENode));
+
+ while (expr->type == EFORCELOAD || expr->type == ETYPCON || expr->type == ECOMMA) {
+ if (!TYPE_FITS_IN_REGISTER(expr->rtype))
+ break;
+ if (expr->type == ECOMMA) {
+ expr->data.diadic.right = comparewithzero(expr->data.diadic.right);
+ return expr;
+ }
+ expr = expr->data.monadic;
+ }
+
+ if (expr->type == ECOND && TYPE_FITS_IN_REGISTER(expr->rtype)) {
+ tmp = COND_to_COMPARE(expr->data.cond.cond, expr->data.cond.expr1, expr->data.cond.expr2);
+ if (tmp)
+ expr = tmp;
+ }
+
+ if (expr->type >= ELESS && expr->type <= ENOTEQU)
+ return expr;
+
+ if (IS_TYPE_FLOAT(expr->rtype)) {
+ static Float float0 = {0.0};
+
+ expr2->type = EFLOATCONST;
+ expr2->cost = 0;
+ expr2->rtype = (expr->rtype->size == 4) ? (Type *) &stfloat : (Type *) &stdouble;
+ expr2->data.floatval = float0;
+ } else {
+ expr2->type = EINTCONST;
+ expr2->cost = 0;
+ if (TYPE_IS_8BYTES(expr->rtype))
+ expr2->rtype = (Type *) &stsignedlonglong;
+ else
+ expr2->rtype = (Type *) &stsignedint;
+ expr2->data.intval.lo = 0;
+ expr2->data.intval.hi = 0;
+ }
+
+ expr1->type = ENOTEQU;
+ expr1->cost = expr->cost;
+ expr1->rtype = (Type *) &stsignedint;
+ expr1->data.diadic.left = expr;
+ expr1->data.diadic.right = expr2;
+ return expr1;
+}
+
+static void rewritefunctioncallreturningstruct(ENode *expr) {
+ ENode *ret_expr;
+ ENode *copy;
+
+ ret_expr = expr->data.funccall.args->node;
+
+ copy = lalloc(sizeof(ENode));
+ memclrw(copy, sizeof(ENode));
+
+ *copy = *expr;
+ expr->type = ECOMMA;
+ expr->data.diadic.left = copy;
+ expr->data.diadic.right = ret_expr;
+}
+
+static void rewritestrcpy(ENode *expr) {
+ ENode *int_expr;
+ ENodeList *list;
+
+ int_expr = lalloc(sizeof(ENode));
+ memclrw(int_expr, sizeof(ENode));
+ int_expr->type = EINTCONST;
+ int_expr->cost = 0;
+ int_expr->flags = 0;
+ int_expr->rtype = (Type *) &stunsignedlong;
+ CInt64_SetLong(&int_expr->data.intval, expr->data.funccall.args->next->node->data.string.size);
+
+ list = lalloc(sizeof(ENodeList));
+ memclrw(list, sizeof(ENodeList));
+ list->next = NULL;
+ list->node = int_expr;
+ expr->data.funccall.args->next->next = list;
+ expr->data.funccall.funcref->data.objref = __memcpy_object;
+}
+
+static SInt32 magnitude(Type *type) {
+ if (IS_TYPE_FLOAT(type))
+ return type->size * 4;
+ else if (is_unsigned(type))
+ return (type->size * 2) + 1;
+ else
+ return type->size * 2;
+}
+
+static Type *promote_type(Type *type) {
+ if (IS_TYPE_ENUM(type))
+ type = TYPE_ENUM(type)->enumtype;
+ if (TYPE_INTEGRAL(type)->integral > stsignedint.integral)
+ return type;
+ else
+ return (Type *) &stsignedint;
+}
+
+static Type *common_type(Type *type1, Type *type2) {
+ Type *tmp;
+
+ if (IS_TYPE_FLOAT(type1) || IS_TYPE_FLOAT(type2)) {
+ if (TYPE_INTEGRAL(type1)->integral > TYPE_INTEGRAL(type2)->integral)
+ return type1;
+ else
+ return type2;
+ }
+
+ type1 = promote_type(type1);
+ type2 = promote_type(type2);
+ if (type1 != type2) {
+ if (TYPE_INTEGRAL(type1)->integral < TYPE_INTEGRAL(type2)->integral) {
+ tmp = type1;
+ type1 = type2;
+ type2 = tmp;
+ }
+
+ if (type1->size == type2->size && !is_unsigned(type1) && is_unsigned(type2)) {
+ if (type1 == (Type *) &stsignedlong) {
+ type1 = (Type *) &stunsignedlong;
+ } else {
+#line 1789
+ CError_ASSERT(type1 == (Type *) &stsignedlonglong);
+ type1 = (Type *) &stunsignedlonglong;
+ }
+ }
+ }
+
+ return type1;
+}
+
+static void rewrite_opassign(ENode *expr, ENodeType exprtype) {
+ ENode *left_sub;
+ ENode *right;
+ Type *left_type;
+ Type *right_type;
+ ENode *new_expr;
+ ENode *tmp;
+ Type *commontype;
+ Type *promo_left;
+ Type *promo_right;
+
+ left_sub = expr->data.diadic.left->data.monadic;
+ right = expr->data.diadic.right;
+ left_type = expr->data.diadic.left->rtype;
+ right_type = expr->data.diadic.right->rtype;
+
+ new_expr = lalloc(sizeof(ENode));
+ memclrw(new_expr, sizeof(ENode));
+ new_expr->type = exprtype;
+ new_expr->rtype = left_type;
+ new_expr->data.diadic.left = expr->data.diadic.left;
+ new_expr->data.diadic.right = right;
+
+ expr->type = EASS;
+ expr->data.diadic.left = left_sub;
+ expr->data.diadic.right = new_expr;
+
+ if (left_sub->type != EOBJREF) {
+ ENode *define;
+ ENode *reuse;
+
+ define = lalloc(sizeof(ENode));
+ memclrw(define, sizeof(ENode));
+ define->type = EDEFINE;
+ define->rtype = left_type;
+
+ reuse = lalloc(sizeof(ENode));
+ memclrw(reuse, sizeof(ENode));
+ reuse->type = EREUSE;
+ reuse->rtype = left_type;
+ reuse->data.monadic = define;
+
+ if (left_sub->type != EBITFIELD) {
+ define->data.monadic = expr->data.diadic.left;
+ expr->data.diadic.left = define;
+ new_expr->data.diadic.left->data.diadic.left = reuse;
+ } else {
+ ENode *copy;
+ define->data.monadic = left_sub->data.diadic.left;
+ left_sub->data.diadic.left = define;
+
+ copy = lalloc(sizeof(ENode));
+ *copy = *left_sub;
+ copy->data.diadic.left = reuse;
+ new_expr->data.diadic.left->data.diadic.left = copy;
+ }
+ }
+
+ switch (exprtype) {
+ case EADD:
+ case ESUB:
+ if (IS_TYPE_POINTER(left_type))
+ break;
+ if (right->type == EINTCONST && TYPE_FITS_IN_REGISTER(left_type))
+ break;
+ case EAND:
+ case EXOR:
+ case EOR:
+ if (left_type == right_type)
+ break;
+ case EMUL:
+ case EDIV:
+ case EMODULO:
+ commontype = common_type(left_type, right_type);
+ if (left_type != commontype) {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = left_type;
+ tmp->data.monadic = expr->data.diadic.right;
+ expr->data.diadic.right = tmp;
+
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = commontype;
+ tmp->data.monadic = new_expr->data.diadic.left;
+ new_expr->data.diadic.left = tmp;
+ }
+ if (right_type != commontype) {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = commontype;
+ tmp->data.monadic = new_expr->data.diadic.right;
+ new_expr->data.diadic.right = tmp;
+ }
+ new_expr->rtype = commontype;
+ break;
+
+ case ESHL:
+ case ESHR:
+ promo_left = promote_type(left_type);
+ promo_right = promote_type(right_type);
+ if (left_type != promo_left) {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = left_type;
+ tmp->data.monadic = expr->data.diadic.right;
+ expr->data.diadic.right = tmp;
+
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = promo_left;
+ tmp->data.monadic = new_expr->data.diadic.left;
+ new_expr->data.diadic.left = tmp;
+ }
+ if (right_type != promo_right) {
+ if (new_expr->data.diadic.right->type == EINTCONST && promo_right == (Type *) &stsignedint) {
+ new_expr->data.diadic.right->rtype = (Type *) &stsignedint;
+ } else {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = promo_right;
+ tmp->data.monadic = new_expr->data.diadic.right;
+ new_expr->data.diadic.right = tmp;
+ }
+ }
+ new_expr->rtype = promo_left;
+ break;
+ }
+}
+
+static void rewrite_preincdec(ENode *expr) {
+ ENode *subexpr; // r31
+ Type *type; // r28
+ ENode *new_expr; // r29
+
+ subexpr = expr->data.monadic;
+ type = expr->rtype;
+
+ new_expr = lalloc(sizeof(ENode));
+ memclrw(new_expr, sizeof(ENode));
+
+ if (IS_TYPE_FLOAT(type)) {
+ new_expr->type = EFLOATCONST;
+ new_expr->cost = 0;
+ new_expr->rtype = type;
+ new_expr->data.floatval = one_point_zero;
+ } else if (IS_TYPE_POINTER(type)) {
+ new_expr->type = EINTCONST;
+ new_expr->cost = 0;
+ new_expr->rtype = (Type *) &stunsignedlong;
+ new_expr->data.intval.hi = 0;
+ new_expr->data.intval.lo = TYPE_POINTER(type)->target->size;
+ } else {
+ new_expr->type = EINTCONST;
+ new_expr->cost = 0;
+ new_expr->rtype = type;
+ new_expr->data.intval.hi = 0;
+ new_expr->data.intval.lo = 1;
+ }
+
+ expr->type = (expr->type == EPREDEC) ? ESUBASS : EADDASS;
+ expr->data.diadic.left = subexpr;
+ expr->data.diadic.right = new_expr;
+}
+
+// Don't know what this would be called in the original, but weh
+typedef union signed_vec {
+ SInt8 sc[16];
+ SInt16 ss[8];
+ SInt32 sl[4];
+} signed_vec;
+
+Boolean canoptimizevectorconst(MWVector128 *vecp, Type *type, COVCResult *result) {
+ // this function is very broken
+ signed_vec vec;
+ union { SInt32 lg; SInt8 ch[4]; } conv32;
+ union { SInt16 sh; SInt8 ch[2]; } conv16;
+ char flag;
+ SInt8 first8;
+ SInt16 first16;
+ SInt32 first32;
+ int i;
+ char ci;
+ UInt32 l0, l1, l2, l3;
+
+ if (IS_TYPE_VECTOR(type)) {
+ vec = *((signed_vec *) vecp);
+
+ first8 = vec.sc[0];
+ flag = 1;
+ for (i = 0; flag && i < 16; i++) {
+ flag = first8 == vec.sc[i];
+ }
+
+ if (flag && first8 < 16 && first8 > -17) {
+ if (result) {
+ result->op1 = PC_VSPLTISB;
+ result->op2 = -1;
+ result->arg = first8;
+ }
+ return 1;
+ }
+
+ first16 = vec.ss[0];
+ flag = 1;
+ for (i = 1; flag && i < 8; i++) {
+ flag = vec.ss[i] == first16;
+ }
+
+ conv16.sh = first16;
+ if (flag && conv16.ch[0] == 0 && conv16.ch[1] < 16 && conv16.ch[1] >= 0) {
+ if (result) {
+ result->op1 = PC_VSPLTISH;
+ result->op2 = -1;
+ result->arg = conv16.ch[1];
+ }
+ return 1;
+ }
+
+ if (flag && conv16.ch[0] == -1 && (conv16.ch[1] & 0xF0) == 0xF0) {
+ if (result) {
+ result->op1 = PC_VSPLTISH;
+ result->op2 = -1;
+ result->arg = conv16.ch[1];
+ }
+ return 1;
+ }
+
+ first32 = vec.sl[0];
+ flag = 1;
+ for (i = 1; flag && i < 4; i++) {
+ flag = vec.sl[i] == first32;
+ }
+
+ conv32.lg = first32;
+ if (flag && conv32.ch[0] == 0 && conv32.ch[1] == 0 && conv32.ch[2] == 0 && conv32.ch[3] < 16 && conv32.ch[3] >= 0) {
+ if (result) {
+ result->op1 = PC_VSPLTISW;
+ result->op2 = -1;
+ result->arg = conv32.ch[3];
+ }
+ return 1;
+ }
+
+ if (flag && conv32.ch[0] == -1 && conv32.ch[1] == -1 && conv32.ch[2] == -1 && (conv32.ch[3] & 0xF0) == 0xF0) {
+ if (result) {
+ result->op1 = PC_VSPLTISW;
+ result->op2 = -1;
+ result->arg = conv32.ch[3];
+ }
+ return 1;
+ }
+
+ l0 = vec.sl[0];
+ l1 = vec.sl[1];
+ l2 = vec.sl[2];
+ l3 = vec.sl[3];
+ for (ci = 0; ci < 16; ci++) {
+ UInt32 *l;
+ UInt32 *r;
+
+ l = (UInt32 *) lvslBytes[(char) ci];
+ r = (UInt32 *) lvsrBytes[(char) ci];
+ if (l0 == l[0] && l1 == l[1] && l2 == l[2] && l3 == l[3]) {
+ if (result) {
+ result->op1 = -1;
+ result->op2 = PC_LVSL;
+ result->arg = ci;
+ }
+ return 1;
+ }
+ if (l0 == r[0] && l1 == r[1] && l2 == r[2] && l3 == r[3]) {
+ if (result) {
+ result->op1 = -1;
+ result->op2 = PC_LVSR;
+ result->arg = ci;
+ }
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static SInt32 countindirects(ENode *expr) {
+ SInt32 tmp1;
+ SInt32 tmp2;
+
+ switch (expr->type) {
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EVECTOR128CONST:
+ return 0;
+ case ECOND:
+ if (expr->data.cond.cond->hascall || expr->data.cond.expr1->hascall || expr->data.cond.expr2->hascall)
+ return 2;
+
+ if ((tmp1 = countindirects(expr->data.cond.cond)) >= 2)
+ return 2;
+ if ((tmp2 = countindirects(expr->data.cond.expr1)) >= 2)
+ return 2;
+ if (tmp2 > tmp1)
+ tmp1 = tmp2;
+ if ((tmp2 = countindirects(expr->data.cond.expr2)) >= 2)
+ return 2;
+ if (tmp2 > tmp1)
+ tmp1 = tmp2;
+ return tmp1;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ return 2;
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ if ((tmp1 = countindirects(expr->data.diadic.left)) >= 2)
+ return 2;
+ if ((tmp2 = countindirects(expr->data.diadic.right)) >= 2)
+ return 2;
+ if (tmp2 > tmp1)
+ tmp1 = tmp2;
+ return tmp1;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EINDIRECT:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ if (expr->type == EINDIRECT)
+ return countindirects(expr->data.monadic) + 1;
+ else
+ return countindirects(expr->data.monadic);
+ default:
+ return 2;
+ }
+}
+
+static Boolean DetectCondSideAffect(ENode *expr) {
+ switch (expr->type) {
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ECOMMA:
+ if (DetectCondSideAffect(expr->data.diadic.left))
+ return 1;
+ return DetectCondSideAffect(expr->data.diadic.right);
+ case EINDIRECT:
+ if (expr->data.monadic->type == EINDIRECT)
+ return 1;
+ if (expr->data.monadic->type == EOBJREF) {
+ if (expr->data.monadic->data.objref->datatype != DDATA && expr->data.monadic->data.objref->datatype != DLOCAL)
+ return 1;
+ if (IS_TYPE_POINTER(expr->data.monadic->data.objref->type))
+ return 1;
+ return Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister != 0;
+ }
+ return 1;
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ return DetectCondSideAffect(expr->data.monadic);
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EVECTOR128CONST:
+ return 0;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOND:
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ case EMFPOINTER:
+ case ENULLCHECK:
+ case EPRECOMP:
+ case EDEFINE:
+ case EREUSE:
+ case EASSBLK:
+ case ECONDASS:
+ return 1;
+ default:
+#line 2523
+ CError_FATAL();
+ return 1;
+ }
+}
+
+static UInt8 WeightandSumOps(ENode *expr) {
+ UInt32 score;
+
+ switch (expr->type) {
+ case ECOND:
+ case ECONDASS:
+ score = WeightandSumOps(expr->data.cond.cond);
+ score += WeightandSumOps(expr->data.cond.expr1);
+ score += WeightandSumOps(expr->data.cond.expr2);
+ break;
+ case EMUL:
+ case EMULV:
+ case EMULASS:
+ score = WeightandSumOps(expr->data.diadic.left) + 10;
+ score += WeightandSumOps(expr->data.diadic.right);
+ break;
+ case EDIV:
+ case EMODULO:
+ case EDIVASS:
+ case EMODASS:
+ score = WeightandSumOps(expr->data.diadic.left) + 20;
+ score += WeightandSumOps(expr->data.diadic.right);
+ break;
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ score = WeightandSumOps(expr->data.diadic.left) + 1;
+ score += WeightandSumOps(expr->data.diadic.right);
+ break;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ score = WeightandSumOps(expr->data.monadic) + 1;
+ break;
+ case EINDIRECT:
+ if (expr->data.monadic->type == EOBJREF && expr->data.monadic->data.objref->datatype == DLOCAL)
+ if (!Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister)
+ return 0;
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ score = WeightandSumOps(expr->data.monadic);
+ break;
+ case EOBJREF:
+ score = 0;
+ break;
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EVECTOR128CONST:
+ score = 0;
+ break;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ score = 5;
+ break;
+ default:
+ score = 255;
+ }
+
+ if (score >= 255)
+ score = 255;
+ return (UInt8) score;
+}
+
+Boolean TOC_use_fsel(ENode *expr) {
+ ENode *left;
+ ENode *right;
+ Type *rtype;
+ int score1;
+ int score2;
+
+ left = expr->data.cond.expr1;
+ right = expr->data.cond.expr2;
+ rtype = expr->rtype;
+
+ if (!copts.peephole) return 0;
+ if (!copts.gen_fsel) return 0;
+ if (left->hascall) return 0;
+ if (right->hascall) return 0;
+ if (!IS_TYPE_FLOAT(rtype)) return 0;
+ if (!IS_TYPE_FLOAT(left->rtype)) return 0;
+ if (!IS_TYPE_FLOAT(right->rtype)) return 0;
+
+ if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU)
+ return 0;
+ if (!IS_TYPE_FLOAT(expr->data.cond.cond->data.diadic.right->rtype))
+ return 0;
+ if (expr->data.cond.cond->type == ELOGNOT || expr->data.cond.cond->type == ELAND || expr->data.cond.cond->type == ELOR)
+ return 0;
+
+ if (expr->type == ECONDASS) {
+ if (left->type != EINDIRECT)
+ return 0;
+ if (left->data.monadic->type != EOBJREF)
+ return 0;
+ }
+
+ if (DetectCondSideAffect(left))
+ return 0;
+ if (DetectCondSideAffect(right))
+ return 0;
+
+ if (expr->type == ECONDASS)
+ score1 = 1;
+ else
+ score1 = WeightandSumOps(left);
+ score2 = WeightandSumOps(right);
+
+ if (score1 > copts.gen_fsel)
+ return 0;
+ else if (score2 > copts.gen_fsel)
+ return 0;
+ else
+ return 1;
+}
+
+Boolean TOC_use_isel(ENode *expr, Boolean flag) {
+ int opt;
+ ENode *left;
+ ENode *right;
+ Type *rtype;
+ Object *obj;
+ int score1;
+ int score2;
+
+ left = expr->data.cond.expr1;
+ right = expr->data.cond.expr2;
+ rtype = expr->rtype;
+ if (flag)
+ opt = 10;
+ else
+ opt = copts.x1E;
+
+ if (!opt) return 0;
+ if (!copts.peephole) return 0;
+ if (left->hascall) return 0;
+ if (right->hascall) return 0;
+ if (!TYPE_FITS_IN_REGISTER(rtype)) return 0;
+ if (!TYPE_FITS_IN_REGISTER(left->rtype)) return 0;
+ if (!TYPE_FITS_IN_REGISTER(right->rtype)) return 0;
+
+ if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU)
+ return 0;
+ if (TYPE_IS_8BYTES(rtype))
+ return 0;
+
+ if (flag) {
+ if (!TYPE_FITS_IN_REGISTER(expr->data.cond.cond->data.diadic.right->rtype))
+ return 0;
+ if (TYPE_IS_8BYTES(expr->data.cond.cond->data.diadic.right->rtype))
+ return 0;
+ }
+
+ if (expr->type == ECONDASS) {
+ if (left->type != EINDIRECT)
+ return 0;
+ if (left->data.monadic->type != EOBJREF)
+ return 0;
+ if (flag) {
+ obj = left->data.monadic->data.objref;
+ if (obj->datatype != DLOCAL)
+ return 0;
+ if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0)
+ return 0;
+ if (obj->u.var.info->rclass != RegClass_GPR)
+ return 0;
+ }
+ }
+
+ if (DetectCondSideAffect(left))
+ return 0;
+ if (DetectCondSideAffect(right))
+ return 0;
+
+ if (expr->type == ECONDASS)
+ score1 = 1;
+ else
+ score1 = WeightandSumOps(left);
+ score2 = WeightandSumOps(right);
+
+ if (score1 > opt)
+ return 0;
+ else if (score2 > opt)
+ return 0;
+ else
+ return 1;
+}
+
+SInt32 GetSizeSkip(ENode *expr) {
+ if (expr->type == EASS)
+ expr = expr->data.diadic.right;
+ if (expr->type == ETYPCON && expr->data.monadic->rtype->size < expr->rtype->size)
+ return expr->data.monadic->rtype->size;
+ else
+ return expr->rtype->size;
+}
+
+void Optimize64bitMath(ENode *expr) {
+ ENode *left; // r23
+ ENode *right; // r28
+ SInt32 leftsize; // r24
+ SInt32 rightsize; // r25
+ SInt32 totalsize; // r22
+ int unsignedflag; // r4
+
+#line 2886
+ CError_ASSERT(TYPE_IS_8BYTES(expr->rtype));
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ leftsize = GetSizeSkip(left);
+ totalsize = (leftsize + (rightsize = GetSizeSkip(right)));
+ unsignedflag = is_unsigned(expr->rtype) != 0;
+
+ switch (totalsize) {
+ case 2:
+ case 3:
+ case 4:
+ if (unsignedflag) {
+ left->rtype = (Type *) &stunsignedint;
+ right->rtype = (Type *) &stunsignedint;
+ } else {
+ left->rtype = (Type *) &stsignedint;
+ right->rtype = (Type *) &stsignedint;
+ }
+ break;
+ case 5:
+ case 6:
+ case 8:
+ case 9:
+ case 10:
+ case 12:
+ if (expr->type != ESUB || leftsize >= rightsize) {
+ if (leftsize < 4) {
+ if (unsignedflag)
+ left->rtype = (Type *) &stunsignedint;
+ else
+ left->rtype = (Type *) &stsignedint;
+ } else {
+ if (left->type == ETYPCON && left->data.monadic->rtype != (Type *) &stfloat)
+ expr->data.diadic.left = left->data.monadic;
+ }
+ if (rightsize < 4) {
+ if (unsignedflag)
+ right->rtype = (Type *) &stunsignedint;
+ else
+ right->rtype = (Type *) &stsignedint;
+ } else {
+ if (right->type == ETYPCON && right->data.monadic->rtype != (Type *) &stfloat)
+ expr->data.diadic.right = right->data.monadic;
+ }
+ }
+ break;
+ case 16:
+ break;
+ default:
+#line 2975
+ CError_FATAL();
+ }
+}
+
+static Boolean OptimizeNestedAssginments(ENode **pexpr, Object *check) {
+ ENode *expr;
+ Boolean success1;
+ Boolean success2;
+
+ expr = *pexpr;
+ switch (expr->type) {
+ case EOBJREF:
+ return check != expr->data.objref;
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ switch (expr->type) {
+ case EASS:
+ if (ENODE_IS(expr->data.diadic.left, EOBJREF) && expr->data.diadic.left->data.objref == check) {
+ *pexpr = expr->data.diadic.right;
+ return OptimizeNestedAssginments(pexpr, check);
+ }
+ break;
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+#line 3033
+ CError_FATAL();
+ return 0;
+ }
+ if (OptimizeNestedAssginments(&expr->data.diadic.right, check))
+ return OptimizeNestedAssginments(&expr->data.diadic.left, check);
+ else
+ return 0;
+ break;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EINDIRECT:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ return OptimizeNestedAssginments(&expr->data.monadic, check);
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EVECTOR128CONST:
+ return 1;
+ case ECOND:
+ success2 = OptimizeNestedAssginments(&expr->data.cond.expr2, check);
+ success1 = OptimizeNestedAssginments(&expr->data.cond.expr1, check);
+ if (!success2 || !success1)
+ return 0;
+ return OptimizeNestedAssginments(&expr->data.cond.cond, check) == 0;
+ case ECONDASS:
+ if (!OptimizeNestedAssginments(&expr->data.cond.expr2, check))
+ return 0;
+ if (OptimizeNestedAssginments(&expr->data.cond.cond, check))
+ return OptimizeNestedAssginments(&expr->data.cond.expr1, check) == 0;
+ else
+ return 0;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ case EMFPOINTER:
+ case ENULLCHECK:
+ case EPRECOMP:
+ case EDEFINE:
+ case EREUSE:
+ case EASSBLK:
+ return 0;
+ default:
+#line 3083
+ CError_FATAL();
+ return 0;
+ }
+}
+
+static void expandTOCexpression(ENode *expr, Type *type, int ignored) {
+ Object *obj;
+ Object *tmpobj;
+ ENode *cond;
+ ENode *tmpexpr;
+ ENode *newexpr;
+ ENodeList *list;
+
+ expr->ignored = ignored;
+ switch (expr->type) {
+ case EINTCONST:
+ expr->hascall = 0;
+ break;
+ case EFLOATCONST:
+ uses_globals = 1;
+ RewriteFloatConst(expr);
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ case EVECTOR128CONST:
+ if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, NULL)) {
+ uses_globals = 1;
+ RewriteVectorConst(expr);
+ expandTOCexpression(expr, NULL, 0);
+ }
+ break;
+ case ESTRINGCONST:
+ uses_globals = 1;
+ CInit_RewriteString(expr, 1);
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ case EOBJREF:
+ obj = expr->data.objref;
+#line 3203
+ CError_ASSERT(obj->datatype != DALIAS);
+ if (obj->datatype == DFUNC || obj->datatype == DVFUNC)
+ uses_globals = 1;
+ if (obj->datatype == DDATA) {
+ uses_globals = 1;
+ if (createIndirect(obj, 0, 1)) {
+ tmpexpr = lalloc(sizeof(ENode));
+ memclrw(tmpexpr, sizeof(ENode));
+ tmpexpr->type = EOBJREF;
+ tmpexpr->cost = 0;
+ tmpexpr->data.objref = obj->toc;
+ tmpexpr->rtype = CDecl_NewPointerType(expr->rtype);
+
+ expr->type = EINDIRECT;
+ expr->cost = 1;
+ expr->data.monadic = tmpexpr;
+ }
+ }
+ expr->hascall = 0;
+ break;
+ case ECONDASS:
+ expr->ignored = 0;
+ case ECOND:
+ if (!ENODE_IS_RANGE(expr->data.cond.cond, ELESS, ENOTEQU))
+ expr->data.cond.cond = comparewithzero(expr->data.cond.cond);
+ expandTOCexpression(expr->data.cond.expr1, NULL, ignored);
+ expandTOCexpression(expr->data.cond.expr2, NULL, ignored);
+ if (TOC_use_fsel(expr)) {
+ cond = expr->data.cond.cond;
+ if (ENODE_IS(cond->data.diadic.right, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.right->data.floatval)) {
+ expandTOCexpression(cond->data.diadic.left, NULL, 0);
+ } else if (ENODE_IS(cond->data.diadic.left, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.left->data.floatval)) {
+ expandTOCexpression(cond->data.diadic.right, NULL, 0);
+ } else {
+ expandTOCexpression(expr->data.cond.cond, NULL, 0);
+ }
+ } else {
+ expandTOCexpression(expr->data.cond.cond, NULL, 0);
+ }
+ expr->hascall = expr->data.cond.cond->hascall | expr->data.cond.expr1->hascall | expr->data.cond.expr2->hascall;
+ break;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ if (is_intrinsic_function_call(expr)) {
+ expr->hascall = 0;
+ if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == INTRINSIC_8) {
+ if (copts.altivec_model)
+ update_frame_align(16);
+ dynamic_stack = 1;
+ requires_frame = 1;
+ } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == INTRINSIC_35) {
+ if (expr->data.funccall.args->next->node->type == ESTRINGCONST) {
+ rewritestrcpy(expr);
+ } else {
+ requires_frame = 1;
+ makes_call = 1;
+ expr->hascall = 1;
+ }
+ } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == INTRINSIC_36) {
+ if (expr->data.funccall.args->next->next->node->type != EINTCONST) {
+ requires_frame = 1;
+ makes_call = 1;
+ expr->hascall = 1;
+ }
+ }
+ } else {
+ requires_frame = 1;
+ makes_call = 1;
+ expr->hascall = 1;
+ }
+
+ if (disables_optimizer(expr)) {
+ disable_optimizer |= 1;
+ if (copts.disable_registers)
+ disable_optimizer |= 2;
+ }
+
+ if (ENODE_IS(expr->data.funccall.funcref, EINDIRECT) && IS_TYPE_FUNC(expr->data.funccall.funcref->rtype))
+ *expr->data.funccall.funcref = *expr->data.funccall.funcref->data.monadic;
+
+ if (ENODE_IS(expr->data.funccall.funcref, EOBJREF)) {
+ expr->data.funccall.funcref->hascall = 0;
+ if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC && (expr->data.funccall.funcref->flags & ENODE_FLAG_80)) {
+ tmpobj = galloc(sizeof(Object));
+ *tmpobj = *expr->data.funccall.funcref->data.objref;
+ tmpobj->datatype = DFUNC;
+ expr->data.funccall.funcref->data.objref = tmpobj;
+ }
+ } else {
+ expandTOCexpression(expr->data.funccall.funcref, NULL, 0);
+ }
+
+ for (list = expr->data.funccall.args; list; list = list->next)
+ expandTOCexpression(list->node, NULL, 0);
+
+ if (expr->hascall)
+ estimate_func_param_size(expr);
+
+ if (is_intrinsic_function_call(expr)) {
+ for (list = expr->data.funccall.args; list; list = list->next)
+ expr->hascall |= list->node->hascall;
+ }
+
+ if (CMach_PassResultInHiddenArg(TYPE_FUNC(expr->data.funccall.functype)->functype))
+ rewritefunctioncallreturningstruct(expr);
+
+ break;
+ case ECOMMA:
+ expandTOCexpression(expr->data.diadic.left, NULL, 1);
+ expandTOCexpression(expr->data.diadic.right, NULL, ignored);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+ case ELAND:
+ case ELOR:
+ if (!ENODE_IS(expr->data.diadic.left, ELOGNOT) && !ENODE_IS2(expr->data.diadic.left, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.left, ELESS, ENOTEQU))
+ expr->data.diadic.left = comparewithzero(expr->data.diadic.left);
+ if (!ENODE_IS(expr->data.diadic.right, ELOGNOT) && !ENODE_IS2(expr->data.diadic.right, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.right, ELESS, ENOTEQU))
+ expr->data.diadic.right = comparewithzero(expr->data.diadic.right);
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+ case EDIVASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EDIV);
+ goto opassign_common;
+ case EMULASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EMUL);
+ goto opassign_common;
+ case EADDASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EADD);
+ goto opassign_common;
+ case ESUBASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, ESUB);
+ goto opassign_common;
+ case EMODASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EMODULO);
+ goto opassign_common;
+ case ESHLASS:
+ rewrite_opassign(expr, ESHL);
+ goto opassign_common;
+ case ESHRASS:
+ rewrite_opassign(expr, ESHR);
+ goto opassign_common;
+ case EANDASS:
+ rewrite_opassign(expr, EAND);
+ goto opassign_common;
+ case EXORASS:
+ rewrite_opassign(expr, EXOR);
+ goto opassign_common;
+ case EORASS:
+ rewrite_opassign(expr, EOR);
+ goto opassign_common;
+ case EASS:
+ if (ENODE_IS(expr->data.diadic.left, EINDIRECT))
+ expr->data.diadic.left = expr->data.diadic.left->data.monadic;
+ opassign_common:
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+ case EEQU:
+ case ENOTEQU:
+ if (ENODE_IS(expr->data.diadic.right, EINTCONST) && expr->data.diadic.right->data.intval.lo == 0 && expr->data.diadic.right->data.intval.hi == 0) {
+ for (tmpexpr = expr->data.diadic.left; ENODE_IS2(tmpexpr, EFORCELOAD, ETYPCON); tmpexpr = tmpexpr->data.monadic) {
+ if (!TYPE_FITS_IN_REGISTER(tmpexpr->rtype))
+ break;
+ }
+ if (ENODE_IS(tmpexpr, ELOGNOT) && TYPE_FITS_IN_REGISTER(tmpexpr->data.monadic->rtype)) {
+ if (ENODE_IS(expr, EEQU))
+ expr->type = ENOTEQU;
+ else
+ expr->type = EEQU;
+ expr->data.diadic.left = tmpexpr->data.monadic;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ if (ENODE_IS(tmpexpr, EEQU)) {
+ if (ENODE_IS(expr, EEQU))
+ tmpexpr->type = ENOTEQU;
+ *expr = *tmpexpr;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ if (ENODE_IS(tmpexpr, ENOTEQU)) {
+ if (ENODE_IS(expr, EEQU))
+ tmpexpr->type = EEQU;
+ *expr = *tmpexpr;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ if (ENODE_IS(tmpexpr, ECOND)) {
+ newexpr = COND_to_COMPARE(tmpexpr->data.cond.cond, tmpexpr->data.cond.expr1, tmpexpr->data.cond.expr2);
+ if (newexpr) {
+ *tmpexpr = *newexpr;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ }
+ }
+ case EDIV:
+ if (ENODE_IS(expr, EDIV) && ENODE_IS(expr->data.diadic.right, EFLOATCONST) && CMach_FloatIsPowerOf2(expr->data.diadic.right->data.floatval)) {
+ expr->type = EMUL;
+ expr->data.diadic.right->data.floatval = CMach_FloatReciprocal(expr->data.diadic.right->data.floatval);
+ }
+ case EMODULO:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ if (TYPE_IS_8BYTES(expr->rtype)) {
+ if (ENODE_IS2(expr, ESHL, ESHR) && !ENODE_IS(expr->data.diadic.right, EINTCONST)) {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+ if (ENODE_IS2(expr, EDIV, EMODULO)) {
+ if (ENODE_IS(expr->data.diadic.right, EINTCONST)) {
+ if (I8_log2n(((SInt64) expr->data.diadic.right->data.intval.hi << 32) + expr->data.diadic.right->data.intval.lo) <= 0) {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+ } else {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+ }
+ }
+ break;
+ case ESUB:
+ if (ENODE_IS(expr->data.diadic.right, EINTCONST)) {
+ expr->type = EADD;
+ expr->data.diadic.right->data.intval = CInt64_Neg(expr->data.diadic.right->data.intval);
+ }
+ case EMUL:
+ case EADD:
+ case EAND:
+ case EXOR:
+ case EOR:
+ expandTOCexpression(expr->data.diadic.left, type, 0);
+ expandTOCexpression(expr->data.diadic.right, type, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ if (ENODE_IS3(expr, EMUL, EADD, ESUB) && TYPE_IS_8BYTES(expr->rtype))
+ Optimize64bitMath(expr);
+ if (type) {
+ if (
+ ENODE_IS(expr->data.diadic.left, ETYPCON) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->rtype) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->data.monadic->rtype) &&
+ expr->data.diadic.left->data.monadic->rtype->size >= type->size &&
+ !TYPE_IS_8BYTES(expr->data.diadic.left->data.monadic->rtype)
+ )
+ expr->data.diadic.left = expr->data.diadic.left->data.monadic;
+
+ if (
+ ENODE_IS(expr->data.diadic.right, ETYPCON) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->rtype) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->data.monadic->rtype) &&
+ expr->data.diadic.right->data.monadic->rtype->size >= type->size &&
+ !TYPE_IS_8BYTES(expr->data.diadic.right->data.monadic->rtype)
+ )
+ expr->data.diadic.right = expr->data.diadic.right->data.monadic;
+
+ expr->rtype = type;
+ }
+ break;
+
+ case ETYPCON:
+ tmpexpr = expr->data.monadic;
+ if ((IS_TYPE_INT_OR_ENUM(expr->rtype) && expr->rtype->size < 4) && IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && !TYPE_IS_8BYTES(tmpexpr->rtype)) {
+ expandTOCexpression(tmpexpr, expr->rtype, 0);
+ } else {
+ expandTOCexpression(tmpexpr, NULL, expr->rtype->type == TYPEVOID);
+ }
+
+ expr->hascall = tmpexpr->hascall;
+ if (IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype))
+ uses_globals = 1;
+
+ if ((TYPE_IS_8BYTES(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) || (TYPE_IS_8BYTES(expr->rtype) && IS_TYPE_FLOAT(tmpexpr->rtype))) {
+ uses_globals = 1;
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+
+ if (IS_TYPE_FLOAT(tmpexpr->rtype)) {
+ if (is_unsigned(expr->rtype) && expr->rtype->size == 4) {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ } else {
+ uses_globals = 1;
+ }
+ }
+
+ if (IS_TYPE_VECTOR(expr->rtype) && !IS_TYPE_VECTOR(tmpexpr->rtype))
+ PPCError_Error(114);
+ break;
+
+ case EPOSTINC:
+ if (!expr->ignored) {
+ if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype))
+ uses_globals = 1;
+ expandTOCexpression(expr->data.monadic, NULL, 0);
+ expr->hascall = expr->data.monadic->hascall;
+ break;
+ }
+ expr->type = EPREINC;
+ case EPREINC:
+ rewrite_preincdec(expr);
+ rewrite_opassign(expr, EADD);
+ goto opassign_common;
+
+ case EPOSTDEC:
+ if (!expr->ignored) {
+ if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype))
+ uses_globals = 1;
+ expandTOCexpression(expr->data.monadic, NULL, 0);
+ expr->hascall = expr->data.monadic->hascall;
+ break;
+ }
+ expr->type = EPREDEC;
+ case EPREDEC:
+ rewrite_preincdec(expr);
+ rewrite_opassign(expr, ESUB);
+ goto opassign_common;
+
+ case ELOGNOT:
+ if (!ENODE_IS(expr->data.monadic, ELOGNOT) && !ENODE_IS2(expr->data.monadic, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.monadic, ELESS, ENOTEQU))
+ expr->data.monadic = comparewithzero(expr->data.monadic);
+ case EMONMIN:
+ case EBINNOT:
+ tmpexpr = expr->data.monadic;
+ expandTOCexpression(tmpexpr, type, 0);
+ expr->hascall = tmpexpr->hascall;
+ if (type && ENODE_IS(expr->data.monadic, ETYPCON)) {
+ if (IS_TYPE_INT_OR_ENUM(expr->data.monadic->rtype) && IS_TYPE_INT_OR_ENUM(expr->data.monadic->data.monadic->rtype)) {
+ if (expr->data.monadic->data.monadic->rtype->size >= type->size) {
+ expr->data.monadic = expr->data.monadic->data.monadic;
+ expr->rtype = type;
+ }
+ }
+ }
+ break;
+
+ case EINDIRECT:
+ case EFORCELOAD:
+ case EBITFIELD:
+ tmpexpr = expr->data.monadic;
+ expandTOCexpression(tmpexpr, NULL, 0);
+ expr->hascall = tmpexpr->hascall;
+ break;
+
+ case EDEFINE:
+ tmpexpr = expr->data.monadic;
+ expandTOCexpression(tmpexpr, NULL, 0);
+ expr->hascall = tmpexpr->hascall;
+ break;
+
+ case EREUSE:
+ expr->hascall = expr->data.monadic->hascall;
+ break;
+
+ case ENULLCHECK:
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+
+ case EPRECOMP:
+ expr->hascall = 0;
+ break;
+
+ case ELABEL:
+ obj = createcodelabel(expr->data.label);
+ newexpr = lalloc(sizeof(ENode));
+ memclrw(newexpr, sizeof(ENode));
+ newexpr->type = EOBJREF;
+ newexpr->cost = 0;
+ newexpr->data.objref = obj;
+ newexpr->rtype = CDecl_NewPointerType(obj->type);
+
+ expr->type = EINDIRECT;
+ expr->cost = 1;
+ expr->data.monadic = newexpr;
+ expr->hascall = 0;
+ break;
+ }
+}
+
+static void checkexceptionreferences(ExceptionAction *action) {
+ for (; action; action = action->prev) {
+ switch (action->type) {
+ case EAT_DESTROYLOCAL:
+ referenceexception(action->data.destroy_local.local);
+ break;
+ case EAT_DESTROYLOCALCOND:
+ referenceexception(action->data.destroy_local_cond.local);
+ referenceexception(action->data.destroy_local_cond.cond);
+ break;
+ case EAT_DESTROYLOCALOFFSET:
+ referenceexception(action->data.destroy_local_offset.local);
+ break;
+ case EAT_DESTROYLOCALPOINTER:
+ referenceexception(action->data.destroy_local_pointer.pointer);
+ break;
+ case EAT_DESTROYLOCALARRAY:
+ referenceexception(action->data.destroy_local_array.localarray);
+ break;
+ case EAT_DESTROYBASE:
+ referenceexception(action->data.destroy_member.objectptr); // wrong union?
+ break;
+ case EAT_DESTROYPARTIALARRAY:
+ referenceexception(action->data.destroy_partial_array.arraypointer);
+ referenceexception(action->data.destroy_partial_array.arraycounter);
+ referenceexception(action->data.destroy_partial_array.element_size);
+ break;
+ case EAT_DESTROYMEMBER:
+ referenceexception(action->data.destroy_member.objectptr);
+ break;
+ case EAT_DESTROYMEMBERCOND:
+ referenceexception(action->data.destroy_member_cond.objectptr);
+ referenceexception(action->data.destroy_member_cond.cond);
+ break;
+ case EAT_DESTROYMEMBERARRAY:
+ referenceexception(action->data.destroy_member_array.objectptr);
+ break;
+ case EAT_DELETEPOINTER:
+ case EAT_DELETELOCALPOINTER:
+ referenceexception(action->data.delete_pointer.pointerobject);
+ break;
+ case EAT_DELETEPOINTERCOND:
+ referenceexception(action->data.delete_pointer_cond.pointerobject);
+ referenceexception(action->data.delete_pointer_cond.cond);
+ break;
+ case EAT_CATCHBLOCK:
+ referenceexception(action->data.catch_block.catch_object);
+ referenceexception(action->data.catch_block.catch_info_object);
+ break;
+ case EAT_ACTIVECATCHBLOCK:
+ referenceexception(action->data.active_catch_block.catch_info_object);
+ break;
+ }
+ }
+}
+
+void expandTOCreferences(Statement **stmts) {
+ Statement *stmt;
+
+ codelabellist = NULL;
+ exceptionlist = NULL;
+
+ for (stmt = *stmts; stmt; stmt = stmt->next) {
+ curstmtvalue = stmt->value;
+ if (stmt->flags & StmtFlag_1) {
+ has_catch_blocks = 1;
+ dynamic_stack = 1;
+ requires_frame = 1;
+ }
+
+ switch (stmt->type) {
+ case ST_EXPRESSION:
+ expandTOCexpression(stmt->expr, NULL, 1);
+ if (stmt->expr->type == ETYPCON && IS_TYPE_VOID(stmt->expr->rtype))
+ stmt->expr = stmt->expr->data.monadic;
+ break;
+ case ST_GOTOEXPR:
+ expandTOCexpression(stmt->expr, NULL, 0);
+ break;
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ if (stmt->expr->type >= ELESS && stmt->expr->type <= ENOTEQU)
+ stmt->expr = comparewithzero(stmt->expr);
+ expandTOCexpression(stmt->expr, NULL, 0);
+ break;
+ case ST_RETURN:
+ if (!stmt->expr)
+ continue;
+ expandTOCexpression(
+ stmt->expr, NULL,
+ IS_TYPE_ARRAY(stmt->expr->rtype) || IS_TYPE_NONVECTOR_STRUCT(stmt->expr->rtype) || IS_TYPE_CLASS(stmt->expr->rtype) ||
+ IS_TYPE_12BYTES_MEMBERPOINTER(stmt->expr->rtype));
+ break;
+ case ST_SWITCH:
+ uses_globals = 1;
+ expandTOCexpression(stmt->expr, NULL, 0);
+ break;
+ case ST_ENDCATCHDTOR:
+ requires_frame = 1;
+ makes_call = 1;
+ break;
+ case ST_ASM:
+ if (stmt->expr) {
+ // TODO - ASM weirdness here
+ }
+ break;
+ }
+
+ checkexceptionreferences(stmt->dobjstack);
+ }
+}
+
+void resetTOCvarinfo(void) {
+ ObjectList *list;
+
+ for (list = toclist; list; list = list->next)
+ list->object->u.toc.info = CodeGen_GetNewVarInfo();
+}
+
+Boolean needdescriptor(void) {
+ // completely unused, dunno what args this might take
+ return 0;
+}
+
+Object *createstaticinitobject(void) {
+ char buf[100];
+ char *p;
+ Str255 fname;
+ TypeFunc *tfunc;
+ Object *obj;
+
+ COS_FileGetFSSpecInfo(&cparamblkptr->mainFileSpec, NULL, NULL, fname);
+ sprintf(buf, "__sinit_%*.*s", -fname[0], fname[0], &fname[1]);
+ for (p = &buf[1]; *p; p++) {
+ if (*p == '.')
+ *p = '_';
+ }
+
+ tfunc = galloc(sizeof(TypeFunc));
+ memclrw(tfunc, sizeof(TypeFunc));
+ tfunc->type = TYPEFUNC;
+ tfunc->functype = &stvoid;
+ tfunc->args = NULL;
+ tfunc->flags = FUNC_FLAGS_2;
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = (Type *) tfunc;
+ obj->name = GetHashNameNodeExport(buf);
+ obj->sclass = OBJECT_SCLASS_102;
+ obj->datatype = DFUNC;
+
+ return obj;
+}
+
+static void estimate_func_param_size(ENode *node) {
+ SInt32 work;
+ ENodeList *list;
+ SInt32 align;
+
+ work = 0;
+ for (list = node->data.funccall.args; list; list = list->next) {
+ align = ~7 & (CMach_ArgumentAlignment(list->node->rtype) + 7);
+ work += ~(align - 1) & (list->node->rtype->size + align - 1);
+ }
+
+ estimate_out_param_size(work);
+}