diff options
62 files changed, 30803 insertions, 1539 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3351eef..a67979d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,4 +84,9 @@ add_executable(mwcc compiler_and_linker/unsorted/CPrec.c compiler_and_linker/unsorted/CError.c compiler_and_linker/unsorted/CInt64.c - compiler_and_linker/unsorted/CMachine.c compiler_and_linker/FrontEnd/C/CPrepTokenizer.c compiler_and_linker/FrontEnd/C/CPrep.c) + compiler_and_linker/unsorted/CMachine.c + compiler_and_linker/FrontEnd/C/CPrepTokenizer.c + compiler_and_linker/FrontEnd/C/CPrep.c + compiler_and_linker/unsorted/PCode.c + compiler_and_linker/unsorted/PCodeInfo.c + compiler_and_linker/unsorted/RegisterInfo.c compiler_and_linker/unsorted/Registers.c compiler_and_linker/unsorted/CMangler.c compiler_and_linker/unsorted/CodeGen.c includes/compiler/Operands.h compiler_and_linker/unsorted/Operands.c includes/compiler/PCodeUtilities.h compiler_and_linker/unsorted/PCodeUtilities.c compiler_and_linker/unsorted/TOC.c compiler_and_linker/unsorted/StackFrame.c includes/compiler/StackFrame.h includes/compiler/TOC.h includes/compiler/CInit.h compiler_and_linker/unsorted/CInit.c compiler_and_linker/unsorted/CExpr.c includes/compiler/CExpr.h compiler_and_linker/unsorted/CExpr2.c includes/compiler/CParser.h compiler_and_linker/unsorted/CParser.c compiler_and_linker/unsorted/CDecl.c includes/compiler/CDecl.h compiler_and_linker/unsorted/CABI.c includes/compiler/CABI.h includes/compiler/CMachine.h includes/compiler/CMangler.h includes/compiler/CScope.h includes/compiler/CPrep.h includes/compiler/CPrepTokenizer.h includes/compiler/CodeGen.h includes/compiler/CClass.h compiler_and_linker/unsorted/CClass.c compiler_and_linker/unsorted/CFunc.c includes/compiler/CFunc.h includes/compiler/CInline.h compiler_and_linker/unsorted/CInline.c) diff --git a/PCode.h b/PCode.h deleted file mode 100644 index 601cfdc..0000000 --- a/PCode.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -typedef struct _PCodeArg { - unsigned int _0; - unsigned int _4; - unsigned int _8; -} PCodeArg; - -typedef struct _PCode { - struct _PCode *nextPCode; - struct _PCode *prevPCode; - struct _PCBlock *block; - unsigned int xx_C; - unsigned int _10; - int flags; - unsigned int _18; - unsigned int _1C; - short op; - short argCount; - PCodeArg args[0]; -} PCode; - -typedef struct _PCLabel { - struct _PCLabel *nextLabel; - struct _PCBlock *block; - short resolved; - short index; -} PCLabel; - -typedef struct _PCLink { - struct _PCLink *nextLink; - struct _PCBlock *block; -} PCLink; - -typedef struct _PCBlock { - struct _PCBlock *nextBlock; - struct _PCBlock *prevBlock; - PCLabel *labels; - PCLink *predecessors; - PCLink *successors; - PCode *firstPCode; - PCode *lastPCode; - int blockIndex; - int codeOffset; // in bytes - int loopWeight; - short pcodeCount; - unsigned short flags; -} PCBlock; - -/* PCode Flags */ -enum { - fPCodeFlag1 = 1, - fPCodeFlag2 = 2, - fPCodeFlag4 = 4, - fPCodeFlag8 = 8, - fPCodeFlag10 = 0x10, - fIsPtrOp = 0x20, - fIsConst = 0x40, - fIsVolatile = 0x80, - fSideEffects = 0x100, - fPCodeFlag200 = 0x200, - fPCodeFlag400 = 0x400, - fPCodeFlag800 = 0x800, - fPCodeFlag1000 = 0x1000, - fCommutative = 0x2000, - fIsCSE = 0x4000, - fOverflow = 0x800000, - fLink = 0x1000000, - fBranchNotTaken = 0x4000000, - fBranchTaken = 0x8000000, - fAbsolute = 0x10000000, - fSetsCarry = 0x10000000, -}; - -enum { - fPCBlockFlag1 = 1, - fPCBlockFlag2 = 2, - fPCBlockFlag4 = 4, - fPCBlockFlag8 = 8, - fPCBlockFlag10 = 0x10, - fPCBlockFlag20 = 0x20 -}; - -extern PCBlock *pcbasicblocks; -extern PCBlock *pclastblock; -extern void *prologue; -extern void *epilogue; -extern PCBlock **depthfirstordering; -extern int pcblockcount; -extern int pcloopweight; - -extern void initpcode(); -extern PCode *makepcode(short op, ...); -extern void emitpcode(short op, ...); -extern PCode *copypcode(PCode *pcode); -extern PCLabel *makepclabel(); -extern PCBlock *makepcblock(); -extern void pclabel(PCBlock *block, PCLabel *label); -extern void pcbranch(PCBlock *block, PCLabel *label); -extern void pccomputepredecessors(); -extern void deleteblock(PCBlock *block); -extern void deleteunreachableblocks(); -extern void appendpcode(PCBlock *block, PCode *pcode); -extern void deletepcode(PCode *pcode); -extern void insertpcodebefore(PCode *anchor, PCode *newpcode); -extern void insertpcodeafter(PCode *anchor, PCode *newpcode); -extern void setpcodeflags(int flags); -extern void clearpcodeflags(int flags); -extern int pccomputeoffsets(); -extern void computedepthfirstordering(); diff --git a/PCodeInfo.c b/PCodeInfo.c deleted file mode 100644 index 9d469bc..0000000 --- a/PCodeInfo.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "PCodeInfo.h" - -void pcode_get_hi_lo(int a1, char a2, int *pA, int *pB) { - -} - -int pcode_check_imm_bits(int a1, int a2, int a3) { - -} - -int pcode_const_from_format(char *buf, int *pResult) { - -} - -PCode *vformatpcode(short opcode, va_list argList) { - -} - -int expectandformatoperand(PCodeArg *operand, unsigned char expectedKind, char a3, int bitCount, char *buf) { -} - -int formatoperand(PCodeArg *operand, char *buf) { - -} - -void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { - -} - -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) { - -} - -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->flags & (fPCodeFlag1 | fPCodeFlag8))) - pcode->flags &= ~fPCodeFlag10; - pcode->op = opcode; -} diff --git a/PCodeInfo.h b/PCodeInfo.h deleted file mode 100644 index 9e3b048..0000000 --- a/PCodeInfo.h +++ /dev/null @@ -1,462 +0,0 @@ -#pragma once - -#include "PCode.h" - -typedef struct _OpcodeInfo { - const char *name; - const char *format; - unsigned char x8; - unsigned char x9; - int xA; - unsigned int insn; -} OpcodeInfo; - -enum { - PC_B = 0x0, - PC_BL = 0x1, - PC_BC = 0x2, - PC_BCLR = 0x3, - PC_BCCTR = 0x4, - PC_BT = 0x5, - PC_BTLR = 0x6, - PC_BTCTR = 0x7, - PC_BF = 0x8, - PC_BFLR = 0x9, - PC_BFCTR = 0xA, - PC_BDNZ = 0xB, - PC_BDNZT = 0xC, - PC_BDNZF = 0xD, - PC_BDZ = 0xE, - PC_BDZT = 0xF, - PC_BDZF = 0x10, - PC_BLR = 0x11, - PC_BCTR = 0x12, - PC_BCTRL = 0x13, - PC_BLRL = 0x14, - PC_LBZ = 0x15, - PC_LBZU = 0x16, - PC_LBZX = 0x17, - PC_LBZUX = 0x18, - PC_LHZ = 0x19, - PC_LHZU = 0x1A, - PC_LHZX = 0x1B, - PC_LHZUX = 0x1C, - PC_LHA = 0x1D, - PC_LHAU = 0x1E, - PC_LHAX = 0x1F, - PC_LHAUX = 0x20, - PC_LHBRX = 0x21, - PC_LWZ = 0x22, - PC_LWZU = 0x23, - PC_LWZX = 0x24, - PC_LWZUX = 0x25, - PC_LWBRX = 0x26, - PC_LMW = 0x27, - PC_STB = 0x28, - PC_STBU = 0x29, - PC_STBX = 0x2A, - PC_STBUX = 0x2B, - PC_STH = 0x2C, - PC_STHU = 0x2D, - PC_STHX = 0x2E, - PC_STHUX = 0x2F, - PC_STHBRX = 0x30, - PC_STW = 0x31, - PC_STWU = 0x32, - PC_STWX = 0x33, - PC_STWUX = 0x34, - PC_STWBRX = 0x35, - PC_STMW = 0x36, - PC_DCBF = 0x37, - PC_DCBST = 0x38, - PC_DCBT = 0x39, - PC_DCBTST = 0x3A, - PC_DCBZ = 0x3B, - PC_ADD = 0x3C, - PC_ADDC = 0x3D, - PC_ADDE = 0x3E, - PC_ADDI = 0x3F, - PC_ADDIC = 0x40, - PC_ADDICR = 0x41, - PC_ADDIS = 0x42, - PC_ADDME = 0x43, - PC_ADDZE = 0x44, - PC_DIVW = 0x45, - PC_DIVWU = 0x46, - PC_MULHW = 0x47, - PC_MULHWU = 0x48, - PC_MULLI = 0x49, - PC_MULLW = 0x4A, - PC_NEG = 0x4B, - PC_SUBF = 0x4C, - PC_SUBFC = 0x4D, - PC_SUBFE = 0x4E, - PC_SUBFIC = 0x4F, - PC_SUBFME = 0x50, - PC_SUBFZE = 0x51, - PC_CMPI = 0x52, - PC_CMP = 0x53, - PC_CMPLI = 0x54, - PC_CMPL = 0x55, - PC_ANDI = 0x56, - PC_ANDIS = 0x57, - PC_ORI = 0x58, - PC_ORIS = 0x59, - PC_XORI = 0x5A, - PC_XORIS = 0x5B, - PC_AND = 0x5C, - PC_OR = 0x5D, - PC_XOR = 0x5E, - PC_NAND = 0x5F, - PC_NOR = 0x60, - PC_EQV = 0x61, - PC_ANDC = 0x62, - PC_ORC = 0x63, - PC_EXTSB = 0x64, - PC_EXTSH = 0x65, - PC_CNTLZW = 0x66, - PC_RLWINM = 0x67, - PC_RLWNM = 0x68, - PC_RLWIMI = 0x69, - PC_SLW = 0x6A, - PC_SRW = 0x6B, - PC_SRAWI = 0x6C, - PC_SRAW = 0x6D, - PC_CRAND = 0x6E, - PC_CRANDC = 0x6F, - PC_CREQV = 0x70, - PC_CRNAND = 0x71, - PC_CRNOR = 0x72, - PC_CROR = 0x73, - PC_CRORC = 0x74, - PC_CRXOR = 0x75, - PC_MCRF = 0x76, - PC_MTXER = 0x77, - PC_MTCTR = 0x78, - PC_MTLR = 0x79, - PC_MTCRF = 0x7A, - PC_MTMSR = 0x7B, - PC_MTSPR = 0x7C, - PC_MFMSR = 0x7D, - PC_MFSPR = 0x7E, - PC_MFXER = 0x7F, - PC_MFCTR = 0x80, - PC_MFLR = 0x81, - PC_MFCR = 0x82, - PC_MFFS = 0x83, - PC_MTFSF = 0x84, - PC_EIEIO = 0x85, - PC_ISYNC = 0x86, - PC_SYNC = 0x87, - PC_RFI = 0x88, - PC_LI = 0x89, - PC_LIS = 0x8A, - PC_MR = 0x8B, - PC_NOP = 0x8C, - PC_NOT = 0x8D, - PC_LFS = 0x8E, - PC_LFSU = 0x8F, - PC_LFSX = 0x90, - PC_LFSUX = 0x91, - PC_LFD = 0x92, - PC_LFDU = 0x93, - PC_LFDX = 0x94, - PC_LFDUX = 0x95, - PC_STFS = 0x96, - PC_STFSU = 0x97, - PC_STFSX = 0x98, - PC_STFSUX = 0x99, - PC_STFD = 0x9A, - PC_STFDU = 0x9B, - PC_STFDX = 0x9C, - PC_STFDUX = 0x9D, - PC_FMR = 0x9E, - PC_FABS = 0x9F, - PC_FNEG = 0xA0, - PC_FNABS = 0xA1, - PC_FADD = 0xA2, - PC_FADDS = 0xA3, - PC_FSUB = 0xA4, - PC_FSUBS = 0xA5, - PC_FMUL = 0xA6, - PC_FMULS = 0xA7, - PC_FDIV = 0xA8, - PC_FDIVS = 0xA9, - PC_FMADD = 0xAA, - PC_FMADDS = 0xAB, - PC_FMSUB = 0xAC, - PC_FMSUBS = 0xAD, - PC_FNMADD = 0xAE, - PC_FNMADDS = 0xAF, - PC_FNMSUB = 0xB0, - PC_FNMSUBS = 0xB1, - PC_FRES = 0xB2, - PC_FRSQRTE = 0xB3, - PC_FSEL = 0xB4, - PC_FRSP = 0xB5, - PC_FCTIW = 0xB6, - PC_FCTIWZ = 0xB7, - PC_FCMPU = 0xB8, - PC_FCMPO = 0xB9, - PC_LWARX = 0xBA, - PC_LSWI = 0xBB, - PC_LSWX = 0xBC, - PC_STFIWX = 0xBD, - PC_STSWI = 0xBE, - PC_STSWX = 0xBF, - PC_STWCX = 0xC0, - PC_ECIWX = 0xC1, - PC_ECOWX = 0xC2, - PC_DCBI = 0xC3, - PC_ICBI = 0xC4, - PC_MCRFS = 0xC5, - PC_MCRXR = 0xC6, - PC_MFTB = 0xC7, - PC_MFSR = 0xC8, - PC_MTSR = 0xC9, - PC_MFSRIN = 0xCA, - PC_MTSRIN = 0xCB, - PC_MTFSB0 = 0xCC, - PC_MTFSB1 = 0xCD, - PC_MTFSFI = 0xCE, - PC_SC = 0xCF, - PC_FSQRT = 0xD0, - PC_FSQRTS = 0xD1, - PC_TLBIA = 0xD2, - PC_TLBIE = 0xD3, - PC_TLBLD = 0xD4, - PC_TLBLI = 0xD5, - PC_TLBSYNC = 0xD6, - PC_TW = 0xD7, - PC_TRAP = 0xD8, - PC_TWI = 0xD9, - PC_OPWORD = 0xDA, - PC_MFROM = 0xDB, - PC_DSA = 0xDC, - PC_ESA = 0xDD, - PC_DCCCI = 0xDE, - PC_DCREAD = 0xDF, - PC_ICBT = 0xE0, - PC_ICCCI = 0xE1, - PC_ICREAD = 0xE2, - PC_RFCI = 0xE3, - PC_TLBRE = 0xE4, - PC_TLBSX = 0xE5, - PC_TLBWE = 0xE6, - PC_WRTEE = 0xE7, - PC_WRTEEI = 0xE8, - PC_MFDCR = 0xE9, - PC_MTDCR = 0xEA, - PC_DCBA = 0xEB, - PC_DSS = 0xEC, - PC_DSSALL = 0xED, - PC_DST = 0xEE, - PC_DSTT = 0xEF, - PC_DSTST = 0xF0, - PC_DSTSTT = 0xF1, - PC_LVEBX = 0xF2, - PC_LVEHX = 0xF3, - PC_LVEWX = 0xF4, - PC_LVSL = 0xF5, - PC_LVSR = 0xF6, - PC_LVX = 0xF7, - PC_LVXL = 0xF8, - PC_STVEBX = 0xF9, - PC_STVEHX = 0xFA, - PC_STVEWX = 0xFB, - PC_STVX = 0xFC, - PC_STVXL = 0xFD, - PC_MFVSCR = 0xFE, - PC_MTVSCR = 0xFF, - PC_VADDCUW = 0x100, - PC_VADDFP = 0x101, - PC_VADDSBS = 0x102, - PC_VADDSHS = 0x103, - PC_VADDSWS = 0x104, - PC_VADDUBM = 0x105, - PC_VADDUBS = 0x106, - PC_VADDUHM = 0x107, - PC_VADDUHS = 0x108, - PC_VADDUWM = 0x109, - PC_VADDUWS = 0x10A, - PC_VAND = 0x10B, - PC_VANDC = 0x10C, - PC_VAVGSB = 0x10D, - PC_VAVGSH = 0x10E, - PC_VAVGSW = 0x10F, - PC_VAVGUB = 0x110, - PC_VAVGUH = 0x111, - PC_VAVGUW = 0x112, - PC_VCFSX = 0x113, - PC_VCFUX = 0x114, - PC_VCMPBFP = 0x115, - PC_VCMPEQFP = 0x116, - PC_VCMPEQUB = 0x117, - PC_VCMPEQUH = 0x118, - PC_VCMPEQUW = 0x119, - PC_VCMPGEFP = 0x11A, - PC_VCMPGTFP = 0x11B, - PC_VCMPGTSB = 0x11C, - PC_VCMPGTSH = 0x11D, - PC_VCMPGTSW = 0x11E, - PC_VCMPGTUB = 0x11F, - PC_VCMPGTUH = 0x120, - PC_VCMPGTUW = 0x121, - PC_VCTSXS = 0x122, - PC_VCTUXS = 0x123, - PC_VEXPTEFP = 0x124, - PC_VLOGEFP = 0x125, - PC_VMAXFP = 0x126, - PC_VMAXSB = 0x127, - PC_VMAXSH = 0x128, - PC_VMAXSW = 0x129, - PC_VMAXUB = 0x12A, - PC_VMAXUH = 0x12B, - PC_VMAXUW = 0x12C, - PC_VMINFP = 0x12D, - PC_VMINSB = 0x12E, - PC_VMINSH = 0x12F, - PC_VMINSW = 0x130, - PC_VMINUB = 0x131, - PC_VMINUH = 0x132, - PC_VMINUW = 0x133, - PC_VMRGHB = 0x134, - PC_VMRGHH = 0x135, - PC_VMRGHW = 0x136, - PC_VMRGLB = 0x137, - PC_VMRGLH = 0x138, - PC_VMRGLW = 0x139, - PC_VMULESB = 0x13A, - PC_VMULESH = 0x13B, - PC_VMULEUB = 0x13C, - PC_VMULEUH = 0x13D, - PC_VMULOSB = 0x13E, - PC_VMULOSH = 0x13F, - PC_VMULOUB = 0x140, - PC_VMULOUH = 0x141, - PC_VNOR = 0x142, - PC_VOR = 0x143, - PC_VPKPX = 0x144, - PC_VPKSHSS = 0x145, - PC_VPKSHUS = 0x146, - PC_VPKSWSS = 0x147, - PC_VPKSWUS = 0x148, - PC_VPKUHUM = 0x149, - PC_VPKUHUS = 0x14A, - PC_VPKUWUM = 0x14B, - PC_VPKUWUS = 0x14C, - PC_VREFP = 0x14D, - PC_VRFIM = 0x14E, - PC_VRFIN = 0x14F, - PC_VRFIP = 0x150, - PC_VRFIZ = 0x151, - PC_VRLB = 0x152, - PC_VRLH = 0x153, - PC_VRLW = 0x154, - PC_VRSQRTEFP = 0x155, - PC_VSL = 0x156, - PC_VSLB = 0x157, - PC_VSLH = 0x158, - PC_VSLO = 0x159, - PC_VSLW = 0x15A, - PC_VSPLTB = 0x15B, - PC_VSPLTH = 0x15C, - PC_VSPLTW = 0x15D, - PC_VSPLTISB = 0x15E, - PC_VSPLTISH = 0x15F, - PC_VSPLTISW = 0x160, - PC_VSR = 0x161, - PC_VSRAB = 0x162, - PC_VSRAH = 0x163, - PC_VSRAW = 0x164, - PC_VSRB = 0x165, - PC_VSRH = 0x166, - PC_VSRO = 0x167, - PC_VSRW = 0x168, - PC_VSUBCUW = 0x169, - PC_VSUBFP = 0x16A, - PC_VSUBSBS = 0x16B, - PC_VSUBSHS = 0x16C, - PC_VSUBSWS = 0x16D, - PC_VSUBUBM = 0x16E, - PC_VSUBUBS = 0x16F, - PC_VSUBUHM = 0x170, - PC_VSUBUHS = 0x171, - PC_VSUBUWM = 0x172, - PC_VSUBUWS = 0x173, - PC_VSUMSWS = 0x174, - PC_VSUM2SWS = 0x175, - PC_VSUM4SBS = 0x176, - PC_VSUM4SHS = 0x177, - PC_VSUM4UBS = 0x178, - PC_VUPKHPX = 0x179, - PC_VUPKHSB = 0x17A, - PC_VUPKHSH = 0x17B, - PC_VUPKLPX = 0x17C, - PC_VUPKLSB = 0x17D, - PC_VUPKLSH = 0x17E, - PC_VXOR = 0x17F, - PC_VMADDFP = 0x180, - PC_VMHADDSHS = 0x181, - PC_VMHRADDSHS = 0x182, - PC_VMLADDUHM = 0x183, - PC_VMSUMMBM = 0x184, - PC_VMSUMSHM = 0x185, - PC_VMSUMSHS = 0x186, - PC_VMSUMUBM = 0x187, - PC_VMSUMUHM = 0x188, - PC_VMSUMUHS = 0x189, - PC_VNMSUBFP = 0x18A, - PC_VPERM = 0x18B, - PC_VSEL = 0x18C, - PC_VSLDOI = 0x18D, - PC_VMR = 0x18E, - PC_VMRP = 0x18F, - PC_SLE = 0x190, - PC_SLEQ = 0x191, - PC_SLIQ = 0x192, - PC_SLLIQ = 0x193, - PC_SLLQ = 0x194, - PC_SLQ = 0x195, - PC_SRAIQ = 0x196, - PC_SRAQ = 0x197, - PC_SRE = 0x198, - PC_SREA = 0x199, - PC_SREQ = 0x19A, - PC_SRIQ = 0x19B, - PC_SRLIQ = 0x19C, - PC_SRLQ = 0x19D, - PC_SRQ = 0x19E, - PC_MASKG = 0x19F, - PC_MASKIR = 0x1A0, - PC_LSCBX = 0x1A1, - PC_DIV = 0x1A2, - PC_DIVS = 0x1A3, - PC_DOZ = 0x1A4, - PC_MUL = 0x1A5, - PC_NABS = 0x1A6, - PC_ABS = 0x1A7, - PC_CLCS = 0x1A8, - PC_DOZI = 0x1A9, - PC_RLMI = 0x1AA, - PC_RRIB = 0x1AB, - PC_PENTRY = 0x1AC, - PC_PEXIT = 0x1AD, - OPCODE_MAX = 0x1AE -}; - -extern OpcodeInfo opcodeInfo[OPCODE_MAX]; - -extern void pcode_get_hi_lo(int a1, char a2, int *pA, int *pB); -extern int pcode_check_imm_bits(int a1, int a2, int a3); -extern int pcode_const_from_format(char *buf, int *pResult); -extern PCode *vformatpcode(short opcode, va_list argList); -extern int expectandformatoperand(PCodeArg *operand, unsigned char expectedKind, char a3, int bitCount, char *buf); -extern int formatoperand(PCodeArg *operand, char *buf); -extern void formatoperands(PCode *pcode, char *buf, int showBasicBlocks); -extern PCode *makecopyinstruction(PCodeArg *a, PCodeArg *b); -extern int is_location_independent(PCode *pcode); -extern int can_reuse_stored_value(PCode *a, PCode *b); -extern int nbytes_loaded_or_stored_by(PCode *pcode); -extern void change_num_operands(PCode *pcode, int newNum); -extern void change_opcode(PCode *pcode, short opcode); diff --git a/command_line/CmdLine/Src/OSLib/Posix.c b/command_line/CmdLine/Src/OSLib/Posix.c index d416b9b..1f13dff 100644 --- a/command_line/CmdLine/Src/OSLib/Posix.c +++ b/command_line/CmdLine/Src/OSLib/Posix.c @@ -956,6 +956,6 @@ int OS_LoadMacResourceFork(const OSSpec *spec, void **file_data, SInt32 *file_le return ENOENT; } -Boolean OS_IsMultiByte(const char *str, int offset) { +Boolean OS_IsMultiByte(const char *str1, const char *str2) { return 0; } 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 = ¯ohashtable[name->hashval], macro = *scan; macro; scan = ¯o->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, ¯o_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/PCode.c b/compiler_and_linker/unsorted/PCode.c index d677e22..0fde159 100644 --- a/PCode.c +++ b/compiler_and_linker/unsorted/PCode.c @@ -1,16 +1,13 @@ -#include "CompilerTools.h" -#include "PCode.h" +#include "compiler.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" -// TODO RESOLVE ME -extern void initialize_aliases(); -extern void *current_statement; -extern PCode *vformatpcode(short op, va_list args); - -PCBlock *pcbasicblocks; -PCBlock *pclastblock; +PCodeBlock *pcbasicblocks; +PCodeBlock *pclastblock; void *prologue; void *epilogue; -PCBlock **depthfirstordering; +PCodeBlock **depthfirstordering; int pcblockcount; int pcloopweight; static unsigned short pclabelcount; @@ -30,7 +27,7 @@ PCode *makepcode(short op, ...) { va_start(list, op); pcode = vformatpcode(op, list); - // TODO + pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1; return pcode; } @@ -40,34 +37,50 @@ void emitpcode(short op, ...) { va_start(list, op); pcode = vformatpcode(op, list); - // TODO + pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1; appendpcode(pclastblock, pcode); } PCode *copypcode(PCode *pcode) { PCode *newpc; - int flag; + 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]; + } - flag = 0; - // TODO + if (extra_arg) + newpc->args[pcode->argCount].kind = PCOp_PLACEHOLDEROPERAND; return newpc; } -PCLabel *makepclabel() { - PCLabel *label; +PCodeLabel *makepclabel() { + PCodeLabel *label; - label = (PCLabel *) lalloc(sizeof(PCLabel)); - memclrw(label, sizeof(PCLabel)); + label = (PCodeLabel *) lalloc(sizeof(PCodeLabel)); + memclrw(label, sizeof(PCodeLabel)); label->index = pclabelcount++; return label; } -PCBlock *makepcblock() { - PCBlock *block; +PCodeBlock *makepcblock() { + PCodeBlock *block; - block = (PCBlock *) lalloc(sizeof(PCBlock)); - memclrw(block, sizeof(PCBlock)); + block = (PCodeBlock *) lalloc(sizeof(PCodeBlock)); + memclrw(block, sizeof(PCodeBlock)); block->loopWeight = pcloopweight; block->blockIndex = pcblockcount++; if (pclastblock) { @@ -80,7 +93,7 @@ PCBlock *makepcblock() { return block; } -void pclabel(PCBlock *block, PCLabel *label) { +void pclabel(PCodeBlock *block, PCodeLabel *label) { PCLink *iter; PCLink *next; @@ -97,7 +110,7 @@ void pclabel(PCBlock *block, PCLabel *label) { block->labels = label; } -void pcbranch(PCBlock *block, PCLabel *label) { +void pcbranch(PCodeBlock *block, PCodeLabel *label) { PCLink *link; link = (PCLink *) lalloc(sizeof(PCLink)); @@ -105,13 +118,13 @@ void pcbranch(PCBlock *block, PCLabel *label) { link->block = label->block; if (!label->resolved) - label->block = (PCBlock *) link; + label->block = (PCodeBlock *) link; link->nextLink = block->successors; block->successors = link; } void pccomputepredecessors() { - PCBlock *block; + PCodeBlock *block; PCLink *succ; PCLink *pred; @@ -127,7 +140,7 @@ void pccomputepredecessors() { } } -void deleteblock(PCBlock *block) { +void deleteblock(PCodeBlock *block) { block->prevBlock->nextBlock = block->nextBlock; if (block->nextBlock) block->nextBlock->prevBlock = block->prevBlock; @@ -135,7 +148,7 @@ void deleteblock(PCBlock *block) { } void deleteunreachableblocks() { - PCBlock *block; + PCodeBlock *block; computedepthfirstordering(); @@ -145,7 +158,7 @@ void deleteunreachableblocks() { } } -void appendpcode(PCBlock *block, PCode *pcode) { +void appendpcode(PCodeBlock *block, PCode *pcode) { if (block->firstPCode) { pcode->nextPCode = 0; pcode->prevPCode = block->lastPCode; @@ -162,7 +175,7 @@ void appendpcode(PCBlock *block, PCode *pcode) { } void deletepcode(PCode *pcode) { - PCBlock *block; + PCodeBlock *block; block = pcode->block; if (pcode->prevPCode) @@ -180,7 +193,7 @@ void deletepcode(PCode *pcode) { } void insertpcodebefore(PCode *anchor, PCode *newpcode) { - PCBlock *block; + PCodeBlock *block; block = anchor->block; if (anchor->prevPCode) @@ -190,7 +203,7 @@ void insertpcodebefore(PCode *anchor, PCode *newpcode) { newpcode->nextPCode = anchor; newpcode->prevPCode = anchor->prevPCode; anchor->prevPCode = newpcode; - newpcode->_1C = anchor->_1C; + newpcode->sourceoffset = anchor->sourceoffset; newpcode->block = block; block->pcodeCount++; @@ -198,7 +211,7 @@ void insertpcodebefore(PCode *anchor, PCode *newpcode) { } void insertpcodeafter(PCode *anchor, PCode *newpcode) { - PCBlock *block; + PCodeBlock *block; block = anchor->block; if (anchor->nextPCode) @@ -208,7 +221,7 @@ void insertpcodeafter(PCode *anchor, PCode *newpcode) { newpcode->prevPCode = anchor; newpcode->nextPCode = anchor->nextPCode; anchor->nextPCode = newpcode; - newpcode->_1C = anchor->_1C; + newpcode->sourceoffset = anchor->sourceoffset; newpcode->block = block; block->pcodeCount++; @@ -227,7 +240,7 @@ void clearpcodeflags(int flags) { int pccomputeoffsets() { int offset; - PCBlock *block; + PCodeBlock *block; offset = 0; for (block = pcbasicblocks; block; block = block->nextBlock) { @@ -239,20 +252,20 @@ int pccomputeoffsets() { } typedef struct _DFO { - PCBlock *block; + PCodeBlock *block; PCLink *link; } DFO; static int depthfirstorder; void computedepthfirstordering() { - PCBlock *block; + PCodeBlock *block; PCLink *link; DFO *dfo; int index; - depthfirstordering = (PCBlock **) lalloc(sizeof(PCBlock *) * pcblockcount); - memclrw(depthfirstordering, sizeof(PCBlock *) * pcblockcount); + depthfirstordering = (PCodeBlock **) lalloc(sizeof(PCodeBlock *) * pcblockcount); + memclrw(depthfirstordering, sizeof(PCodeBlock *) * pcblockcount); depthfirstorder = pcblockcount; for (block = pcbasicblocks; block; block = block->nextBlock) { 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); +} diff --git a/includes/compiler.h b/includes/compiler.h index 319f95e..6557749 100644 --- a/includes/compiler.h +++ b/includes/compiler.h @@ -8,276 +8,29 @@ #pragma options align=mac68k #endif -enum { - AlignMode0_Mac68k, - AlignMode1_Mac68k4byte, - AlignMode2_PPC, - AlignMode3_1Byte, - AlignMode4_2Byte, - AlignMode5_4Byte, - AlignMode6_8Byte, - AlignMode7_16Byte, - AlignMode8 -}; -// not sure how many of these are char and how many are unsigned char or Boolean -typedef struct COpts { - char little_endian; - char codegen_dynamic; - char codegen_pic; - char no_common; - char no_implicit_templates; - char absolutepath; // determines the path written to debug info - char x06; // linker/objgen related - short cpu; - char schedule_cpu; - unsigned char schedule_mode; // may be an enum?? - SInt32 debuglisting; - char profile; - char traceback; - char disable_registers; - char fp_contract; - char no_register_save_helpers; - char ppc_unroll_speculative; - short ppc_unroll_instructions_limit; - short ppc_unroll_factor_limit; - char altivec_model; - UInt8 x1B; // altivec/vrsave related - UInt8 code_alignment; - char x1D; - UInt8 x1E; // some register used in TOC_use_isel - UInt8 gen_fsel; - char ppc_opt_bclr_bcctr; - char use_lmw_stmw; - char report_heap_info; - char misaligned_mem_access; - char switch_tables; - char prepare_compress; - char some_alignment; // used in CMach_AllocationAlignment - char asmsemicolcomment; - char asmpoundcomment; - StringPtr oldprefixname; - short inlinelevel; - int inline_max_size; - int inline_max_total_size; - char inline_bottom_up; - Boolean cplusplus; - Boolean ecplusplus; - char objective_c; - char objc_strict; - char ARM_conform; - char ARM_scoping; - char require_prototypes; - char trigraphs; - char only_std_keywords; - char enumsalwaysint; - char ANSI_strict; - char mpwc_relax; - char mpwc_newline; - char ignore_oldstyle; - char cpp_extensions; - char pointercast_lvalue; - char useRTTI; - char delete_exception; - char _4B; - Boolean oldalignment; - char unsignedchars; - char multibyteaware; - char autoinline; - char defer_codegen; - Boolean direct_to_som; - char som_env_check; - char som_call_opt; - char booltruefalse; - char old_enum_mangler; - char longlong; - char longlong_enums; - char no_tfuncinline; - char _59; - char flat_include; - char syspath_once; - char always_import; - char simple_class_byval; - char wchar_type; - char vbase_ctor_offset; - char vbase_abi_v2; - char def_inherited; - char template_patch; - char template_friends; - char faster_pch_gen; - char array_new_delete; - Boolean dollar_identifiers; - char def_inline_tfuncs; - char arg_dep_lookup; - Boolean simple_prepdump; - char line_prepdump; - char fullpath_prepdump; - char old_mtemplparser; - char suppress_init_code; - char reverse_bitfields; - Boolean c9x; - char float_constants; - char no_static_dtors; - char longlong_prepeval; - char const_strings; - char dumpir; - char experimental; - char gcc_extensions; - char stdc_fp_contract; - char stdc_fenv_access; - char stdc_cx_limitedr; - char old_argmatch; - char optEH; - char optEH2; - char new_mangler; - char microsoft; - Boolean warningerrors; - char pedantic; - char check_header_flags; - Boolean supress_warnings; - Boolean warn_illpragma; - char warn_emptydecl; - char warn_possunwant; - char warn_unusedvar; - char warn_unusedarg; - char warn_extracomma; - char warn_hidevirtual; - char warn_largeargs; - char warn_implicitconv; - char warn_notinlined; - char warn_structclass; - char warn_padding; - char warn_no_side_effect; - char warn_resultnotused; - char warn_ptr_int_conv; - char align_mode; - Boolean align_array_members; - char dont_reuse_strings; - char pool_strings; - char explicit_zero_data; - char readonly_strings; - char exceptions; - char _99; - char dont_inline; - char always_inline; - char peephole; - char global_optimizer; - char side_effects; - char internal; - char import; - char export; - char lib_export; - char nosyminline; - char force_active; - char optimizationlevel; - char optimize_for_size; - char optimizewithasm; - char crippled; - char opt_common_subs; - char opt_loop_invariants; - char opt_propagation; - char opt_dead_assignments; - char opt_strength_reduction; - char opt_strength_reduction_strict; - char opt_dead_code; - char opt_lifetimes; - char _B1; // unused? - char opt_unroll_loops; - char opt_vectorize_loops; - char _B4; // amount of IRO passes? - char opt_pointer_analysis; - char opt_pointer_analysis_mode; - char loop_unroll_count; - char loop_unroll_size_threshold; - char isGeneratingDebugInfo; - CWDataType pchCreator; - CWDataType pchType; - CWDataType text; - HashNameNode *forcedSegment; // when set by #pragma segment -} COpts; - -typedef struct CParams { - CWPluginContext context; - CWObjectData objectdata; - Handle objectDataHandle; - Handle browseDataHandle; - SInt32 pluginRequest; - SInt32 apiVersion; - FSSpec projectFile; - SInt32 projectFileCount; - SInt32 mainFileNumber; - FSSpec mainFileSpec; - const char *mainFileText; - SInt32 mainFileTextLength; - Boolean isPrecompiling; - Boolean isAutoPrecompiling; - Boolean isPreprocessing; - Boolean isGeneratingDebugInfo; - Boolean isCachingPrecompiledHeaders; - CWBrowseOptions browseOptions; - Boolean field276; - SInt16 mainFileID; - CWDataType targetOS; - CWDataType targetCPU; - char *targetName; -} CParams; - - -typedef struct VarInfo { // OK! - Object *func; - SInt32 usage; - TStreamElement deftoken; - SInt16 varnumber; - Boolean noregister; - Boolean used; - UInt8 flags; - UInt8 rclass; - SInt16 reg; - SInt16 regHi; -} VarInfo; - - - -typedef struct DefArgCtorInfo { + + + +struct DefArgCtorInfo { Object *default_func; ENode *default_arg; -} DefArgCtorInfo; +}; typedef struct XRefOffset { UInt32 xrefoffset; SInt32 offset; } XRefOffset; -typedef struct InlineXRef { - struct InlineXRef *next; +struct InlineXRef { + InlineXRef *next; Object *object; UInt16 xrefmode; UInt16 numxrefs; XRefOffset xref[1]; -} InlineXRef; - - -typedef enum StatementType { - ST_NOP = 1, - ST_LABEL, - ST_GOTO, - ST_EXPRESSION, - ST_SWITCH, - ST_IFGOTO, - ST_IFNGOTO, - ST_RETURN, - ST_OVF, - ST_EXIT, - ST_ENTRY, - ST_BEGINCATCH, - ST_ENDCATCH, - ST_ENDCATCHDTOR, - ST_GOTOEXPR, - ST_ASM, - ST_BEGINLOOP, - ST_ENDLOOP, - ST_ILLEGAL -} StatementType; +}; + + typedef enum ExceptionActionType { EAT_NOP, @@ -301,8 +54,8 @@ typedef enum ExceptionActionType { EAT_NACTIONS } ExceptionActionType; -typedef struct ExceptionAction { - struct ExceptionAction *prev; +struct ExceptionAction { + ExceptionAction *prev; union { struct { Object *local; @@ -385,32 +138,10 @@ typedef struct ExceptionAction { } local; } data; ExceptionActionType type; -} ExceptionAction; - -typedef struct Statement { - struct Statement *next; - StatementType type; - char marked; - UInt8 flags; - UInt16 value; - ENode *expr; - CLabel *label; - ExceptionAction *dobjstack; - SInt32 sourceoffset; - HashNameNode *sourcefilepath; -} Statement; - -typedef struct CLabel { - struct CLabel *next; - Statement *stmt; - HashNameNode *uniquename; - HashNameNode *name; - PCodeLabel *pclabel; - void *sicg_label; -} CLabel; - -typedef struct MemInitializer { - struct MemInitializer *next; +}; + +struct MemInitializer { + MemInitializer *next; union { ENodeList *nodes; ENode *expr; @@ -421,7 +152,7 @@ typedef struct MemInitializer { } u; Boolean is_ivar; Boolean is_expr; -} MemInitializer; +}; typedef enum DepNameType { @@ -434,8 +165,8 @@ typedef enum DepNameType { DNT_TYPENAME } DepNameType; -typedef struct DepName { - struct DepName *next; +struct DepName { + DepName *next; union { HashNameNode *name; NameSpace *nspace; @@ -453,7 +184,7 @@ typedef struct DepName { } tname; } u; DepNameType type; -} DepName; +}; @@ -479,314 +210,110 @@ typedef struct Substitution { SubKind kind; } Substitution; +// Registers.c +enum { + RegisterMax = 32 +}; +const char RegClass_SPR = 0; +const char RegClass_CRFIELD = 1; +const char RegClass_VR = 2; +const char RegClass_FPR = 3; +const char RegClass_GPR = 4; +const char RegClassMax = 5; +/*enum RegClass { + RegClass_SPR, + RegClass_CRFIELD, + RegClass_VR, + RegClass_FPR, + RegClass_GPR, + RegClassMax +};*/ -// CScope.c -extern Boolean cscope_is_member_func; -extern Object *cscope_currentfunc; -extern TypeClass *cscope_currentclass; -extern NameSpace *cscope_current; -extern NameSpace *cscope_root; - -typedef struct CScopeSave { - NameSpace *current; - TypeClass *currentclass; - Object *currentfunc; - Boolean is_member_func; -} CScopeSave; // assumed name - -typedef struct CScopeParseResult { - NameSpace *nspace_0; - HashNameNode *name_4; - Type *x8; - void *xC; - ObjBase *obj_10; - NameSpaceObjectList *nsol_14; - BClassList *bcl_18; - Boolean x1C; - Boolean x1D; - Boolean isambig; - Boolean x1F; - Boolean x20; - Boolean x21; -} CScopeParseResult; - -typedef struct CScopeNSIterator { - NameSpace *nspace; - NameSpaceLookupList *lookup; - CScopeParseResult *result; -} CScopeNSIterator; - -typedef struct CScopeObjectIterator { - NameSpace *nspace; - NameSpaceName *nextname; - NameSpaceObjectList *currlist; - int hashindex; -} CScopeObjectIterator; - -extern void CScope_Setup(); -extern void CScope_Cleanup(); -extern void CScope_GetScope(CScopeSave *save); -extern void CScope_SetNameSpaceScope(NameSpace *nspace, CScopeSave *save); -extern void CScope_SetClassScope(TypeClass *cls, CScopeSave *save); -extern void CScope_SetClassDefScope(TypeClass *cls, CScopeSave *save); -extern void CScope_SetFunctionScope(Object *function, CScopeSave *save); -extern void CScope_SetMethodScope(Object *function, TypeClass *cls, Boolean unknownFlag, CScopeSave *save); -extern void CScope_RestoreScope(CScopeSave *saved); -extern Boolean CScope_IsEmptySymTable(); -extern Boolean CScope_IsInLocalNameSpace(NameSpace *nspace); -extern NameSpaceObjectList *CScope_FindName(NameSpace *nspace, HashNameNode *name); -extern NameSpaceName *CScope_FindNameSpaceName(NameSpace *nspace, HashNameNode *name); -extern NameSpaceObjectList *CScope_InsertName(NameSpace *nspace, HashNameNode *name); -extern NameSpaceObjectList *CScope_ArgumentDependentNameLookup(NameSpaceObjectList *list, HashNameNode *name, ENodeList *argNodes, Boolean flag); -extern NameSpace *CScope_NewHashNameSpace(HashNameNode *name); -extern NameSpace *CScope_NewListNameSpace(HashNameNode *name, Boolean is_global); -extern NameSpace *CScope_FindNonClassNonFunctionNS(NameSpace *nspace); -extern NameSpace *CScope_FindGlobalNS(NameSpace *nspoce); -extern Boolean CScope_IsStdNameSpace(NameSpace *nspace); -extern Boolean CScope_IsEmptyNameSpace(NameSpace *nspace); -extern void CScope_MergeNameSpace(NameSpace *dst, NameSpace *src); -extern void CScope_AddObject(NameSpace *nspace, HashNameNode *name, ObjBase *obj); -extern void CScope_AddGlobalObject(Object *obj); -extern NameSpaceLookupList *CScope_BuildNameSpaceLookupList(NameSpace *nspace); -extern Boolean CScope_FindQualifiedClassMember(CScopeParseResult *result, TypeClass *tclass, HashNameNode *name); -extern Type *CScope_GetType(NameSpace *nspace, HashNameNode *name, void **unk6); -extern Type *CScope_GetTagType(NameSpace *nspace, HashNameNode *name); -extern Boolean CScope_ParseExprName(CScopeParseResult *result); -extern Boolean CScope_ParseDeclName(CScopeParseResult *result); -extern Boolean CScope_ParseQualifiedNameSpace(CScopeParseResult *result, Boolean flag1, Boolean flag2); -extern Boolean CScope_ParseElaborateName(CScopeParseResult *result); -extern Boolean CScope_FindObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name); -extern Boolean CScope_FindNonClassObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name); -extern NameSpaceObjectList *CScope_FindObjectList(CScopeParseResult *result, HashNameNode *name); -extern Boolean CScope_PossibleTypeName(HashNameNode *name); -extern Boolean CScope_FindClassMemberObject(TypeClass *tclass, CScopeParseResult *result, HashNameNode *name); -extern void CScope_InitObjectIterator(CScopeObjectIterator *iterator, NameSpace *nspace); -extern ObjBase *CScope_NextObjectIteratorObject(CScopeObjectIterator *iterator); -extern NameSpaceObjectList *CScope_NextObjectIteratorObjectList(CScopeObjectIterator *iterator); -extern void CScope_DefineTypeTag(NameSpace *nspace, HashNameNode *name, Type *type); -extern Type *CScope_GetLocalTagType(NameSpace *nspace, HashNameNode *name); -extern Boolean CScope_FindTypeName(NameSpace *nspace, HashNameNode *name, CScopeParseResult *result); -extern NameSpaceObjectList *CScope_GetLocalObject(NameSpace *nspace, HashNameNode *name); -extern BClassList *CScope_GetClassAccessPath(BClassList *list, TypeClass *tclass); -extern Boolean CScope_ParseMemberName(TypeClass *tclass, CScopeParseResult *result, Boolean flag); -extern void CScope_AddClassUsingDeclaration(TypeClass *tclass, TypeClass *tclass2, HashNameNode *name, AccessType access); -extern void CScope_ParseUsingDeclaration(NameSpace *nspace, AccessType access); -extern void CScope_ParseNameSpaceAlias(HashNameNode *name); -extern void CScope_ParseUsingDirective(NameSpace *nspace); - -// CMachine.c -extern TypeIntegral stbool; -extern TypeIntegral stchar; -extern TypeIntegral stsignedchar; -extern TypeIntegral stunsignedchar; -extern TypeIntegral stwchar; -extern TypeIntegral stsignedshort; -extern TypeIntegral stunsignedshort; -extern TypeIntegral stsignedint; -extern TypeIntegral stunsignedint; -extern TypeIntegral stsignedlong; -extern TypeIntegral stunsignedlong; -extern TypeIntegral stsignedlonglong; -extern TypeIntegral stunsignedlonglong; -extern TypeIntegral stfloat; -extern TypeIntegral stshortdouble; -extern TypeIntegral stdouble; -extern TypeIntegral stlongdouble; - -extern TypeStruct stvectorunsignedchar; -extern TypeStruct stvectorsignedchar; -extern TypeStruct stvectorboolchar; -extern TypeStruct stvectorunsignedshort; -extern TypeStruct stvectorsignedshort; -extern TypeStruct stvectorboolshort; -extern TypeStruct stvectorunsignedlong; -extern TypeStruct stvectorsignedlong; -extern TypeStruct stvectorboollong; -extern TypeStruct stvectorfloat; -extern TypeStruct stvectorpixel; -extern TypeStruct stvector; - -extern void CMach_Configure(); -extern SInt32 CMach_GetQUALalign(UInt32 qual); -extern SInt32 CMach_ArgumentAlignment(Type *type); -extern SInt32 CMach_AllocationAlignment(Type *type, UInt32 qual); -extern CInt64 CMach_CalcIntDiadic(Type *type, CInt64 left, short op, CInt64 right); -extern CInt64 CMach_CalcIntMonadic(Type *type, short op, CInt64 val); -extern CInt64 CMach_CalcIntConvertFromFloat(Type *type, Float fval); -extern void CMach_InitIntMem(Type *type, CInt64 val, void *mem); -extern void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem); -extern Float CMach_CalcFloatDiadic(Type *type, Float left, short op, Float right); -extern Float CMach_CalcFloatMonadic(Type *type, short op, Float fval); -extern Boolean CMach_CalcFloatDiadicBool(Type *type, Float left, short op, Float right); -extern Boolean CMach_CalcVectorDiadicBool(Type *type, MWVector128 *left, short op, MWVector128 *right); -extern char *CMach_FloatScan(char *input, Float *result, Boolean *fail); -extern Float CMach_CalcFloatConvertFromInt(Type *type, CInt64 val); -extern Float CMach_CalcFloatConvert(Type *type, Float fval); -extern Boolean CMach_FloatIsZero(Float fval); -extern Boolean CMach_FloatIsOne(Float fval); -extern Boolean CMach_FloatIsNegOne(Float fval); -extern void CMach_InitFloatMem(Type *type, Float val, void *mem); -extern void CMach_PrintFloat(char *buf, Float val); -extern void CMach_PragmaParams(); -extern void CMach_AdjustFuntionArgs(); -extern SInt16 CMach_GetStructAlign(TypeStruct *tstruct); -extern SInt16 CMach_GetClassAlign(TypeClass *tclass); -extern SInt16 CMach_GetTypeAlign(Type *type); -extern SInt16 CMach_MemberAlignValue(Type *type, SInt32 var); -extern void CMach_StructLayoutInitOffset(SInt32 offset); -extern SInt32 CMach_StructLayoutGetCurSize(); -extern SInt32 CMach_StructLayoutGetOffset(Type *type, UInt32 qual); -extern SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual); -extern UInt8 CMach_GetFunctionResultClass(TypeFunc *tfunc); -extern Boolean CMach_PassResultInHiddenArg(Type *type); -extern const char *CMach_GetCPU(); -extern Boolean CMach_FloatIsPowerOf2(Float flt); -extern Float CMach_FloatReciprocal(Float flt); -extern SInt32 CMach_RoundedSizeOf(Object *object); -extern void CMach_ReInitRuntimeObjects(); - -// CPrep.c -typedef struct Macro { - struct Macro *next; - HashNameNode *name; - void *c; - Boolean xC; - Boolean xD; - Boolean is_special; - Boolean xF; - void *e; -} Macro; -typedef struct TokenStack { - char *pos; - char *macrostart; - Macro *macro; - Boolean macrocheck; -} TokenStack; +enum { + RegState0 = 0, + RegState1 = 1, + RegState2 = 2 +}; -extern CParams *cparamblkptr; -extern short tk; -extern CInt64 tkintconst; -extern Float tkfloatconst; -extern char *tkstring; -extern HashNameNode *tkidentifier; -extern SInt32 tksize; -extern short ispascalstring; -extern short nlflag; -extern SInt32 lines; -extern Boolean spaceskip; -extern struct Macro **macrohashtable; -extern Boolean cprep_nomem_exit; -extern Boolean cprep_nostring; -extern Boolean cprep_eoltokens; -extern TokenStack tokenstack[128]; -extern short tokenstacklevel; -extern SInt32 cprep_cursymfile; // might be a ptr? -extern char *pos; -extern char *macropos; -extern char *nextcharpos; -extern char CPrep_SkipNewCommentChar; -extern Boolean preprocessing_only; -extern Handle stringmem; -extern SInt32 maxstringsize; -extern char cprep_idarray[256]; -extern Boolean was_escchar; -extern Boolean macrocheck; -extern Boolean widestring; -extern Boolean at_linestart; -extern char *prep_file_start; -extern char *prep_file_end; -extern char *macrostart; -extern Boolean cprep_strconcat; -extern CPrepFileInfo *prep_file; -extern short filesp; -extern SInt32 linenumber; -extern GList pplist; -extern TStreamElement *ts_current; -extern SInt32 ts_preread_elements; - -extern void CPrep_InsertSpecialMacro(Macro *macro, char *name); -extern void CPrep_InsertSpecialMacros(); -extern void CPrep_RemoveSpecialMacros(); -extern Boolean setupprep(); -extern void cleanupprep(); -extern void CPrep_TSBufferGrow(int amount); -extern void CPrep_TokenStreamGetState(SInt32 *state); -extern void CPrep_TokenStreamSetState(SInt32 *state); -extern void CPrep_UnLex(); -extern void CPrep_TokenStreamSetCurState(SInt32 *state); -extern void CPrep_StreamGetBlock(); -extern void CPrep_StreamGetSemicolon(); -extern void CPrep_StreamGetTemplate(); -extern void CPrep_StreamInsert(); -extern void CPrep_StreamRemove(); -extern void CPrep_RemoveTokens(); -extern void CPrep_TokenStreamFlush(); -extern void CPrep_CurStreamElement(); -extern void CPrep_GetTokenContext(TStreamElement *token, CPrepFileInfo **tokenfile, SInt32 *selectionoffset, short *tokensize, SInt32 *linenumber, char *buf1, short *tokenoffset, short *tokenlength, char *buf2, short *lastarg); -extern void CPrep_Error(short code); -extern void CPrep_ErrorName(short code, const char *name); -extern void CPrep_Warning(short code); -extern void CPrep_WarningName(short code, const char *name); -extern void CPrep_ErrorMessage(int errTable, char *str, Boolean flag1, Boolean flag2); -extern void CPrep_ErrorMessageVA(int code, const char *format, va_list list, Boolean flag1, Boolean flag2); -extern void popfile(); -extern void CPrep_SetSourceFile(); -extern void CPrep_GetSourceFilePath(); -extern void CPrep_NewFileOffsetInfo(); -extern void CPrep_GetFileOffsetInfo(); -extern void CPrep_GetFileOffsetInfo2(); -extern void CPrep_ResetFileInfo(); -extern void CPrep_GetPrepPos(); -extern Boolean C_Compiler(CParams *param); -extern void poptokenseq(); -extern void foundnl(); -extern void newline(); -extern short notendofline(); -extern char *CPrep_GetFileName(char *buffer, Boolean flag1, Boolean flag2); -extern void macrotest(); -extern void CPrep_PragmaLex(); -extern void CPrep_PushOption(); -extern void CPrep_PopOption(); -extern void preprocessor(); -extern void CPrep_BrowserTokenOffset(); -extern void CPrep_BrowserFileOffset(); -extern void CPrep_BrowserFilePosition(CPrepFileInfo **fileinfo, SInt32 *offset); -extern CPrepFileInfo *CPrep_BrowserCurrentFile(); - -// CPrepTokenizer.c -extern short prepskipnextchar(); -extern short prepnextchar(); -extern short prepnextstringchar(char *str, Boolean flag); -extern void CPrep_MatchChar(char ch, Boolean flag); -extern char *CPrep_MatchChar2(char *str, char ch, Boolean flag); -extern short prepcurchar(); -extern char *ReadIdentifier(char *str); -extern char *CPrep_SkipNewComment(char *str); -extern Boolean skipendoflinematch(char *str, Boolean flag); -extern void skipendofline(); -extern void CPrep_SkipAsmComment(); -extern short lookahead(); -extern short lookahead_noeol(); -extern short lex(); -extern short plex(); -extern short lexidentifier(); +extern int used_virtual_registers[RegClassMax]; +extern int used_nonvolatile_registers[RegClassMax]; +extern int assignable_registers[RegClassMax]; +extern int n_real_registers[RegClassMax]; +extern int n_scratch_registers[RegClassMax]; +extern int scratch_registers[RegClassMax][RegisterMax]; +extern int n_nonvolatile_registers[RegClassMax]; +extern int nonvolatile_registers[RegClassMax][RegisterMax]; +extern UInt8 reg_state[RegClassMax][RegisterMax]; +extern int first_temporary_register[RegClassMax]; +extern int last_temporary_register[RegClassMax]; +extern char *register_class_name[RegClassMax]; +extern char *register_class_format[RegClassMax]; +extern int coloring; +extern int optimizing; + +extern void init_registers(); +extern void assign_register_to_variable(Object *obj, char rclass); +extern void retain_register_for_argument(Object *obj, char rclass, short reg); +extern int available_registers(char rclass); +extern UInt32 volatile_registers(char rclass); +extern short obtain_nonvolatile_register(char rclass); +extern void open_temp_registers(); +extern void check_temp_registers(); +extern void close_temp_registers(); +extern int count_scratch_registers(); +extern void init_modified_registers(); +extern void note_modified_registers(Object *obj); +extern void find_modified_registers(Object *obj, UInt32 *masks); + +// RegisterInfo.c +extern short last_exception_register[RegClassMax]; +extern short first_fe_temporary_register[RegClassMax]; +extern short last_argument_register[RegClassMax]; +extern short _FP_; +extern short _CALLER_SP_; +extern char *special_register_names[RegClassMax][RegisterMax]; +extern short spr_to_sysreg[4]; + +extern void asm_used_register(char rclass, short reg); +extern void retain_register(Object *obj, char rclass, short reg); +extern void retain_GPR_pair(Object *obj, short reg, short regHi); +extern int is_register_object(Object *obj); +extern int GetABIFirstNonVolatile(char rclass); +extern char GetRegisterClassName(char rclass); +extern void setup_diagnostic_reg_strings(); +extern void init_target_registers(); +extern void assign_register_by_type(Object *obj); +extern void assign_GPR_pair(Object *obj); +extern void open_fe_temp_registers(); +extern void set_last_exception_registers(); +extern VarInfo *Registers_GetVarInfo(Object *obj); +extern int used_vrstate_VRs(); +extern UInt32 colored_vrs_as_vrsave(PCodeBlock *block); +extern void save_before_coloring_nonvolatile_registers(char rclass); +extern void reset_nonvolatile_registers(char rclass); +extern int is_nonvolatile_register(char rclass, int reg); +extern void init_endian(); +extern void update_asm_nonvolatile_registers(); // LOOSE DECLS -extern Boolean C_Compiler(CParams *param); +extern short high_offset; +extern short low_offset; +extern short high_reg; +extern short low_reg; +extern short high_reg2; +extern short low_reg2; extern void PrecompilerRead(short refnum, void *buffer); +extern void PrecompilerWrite(); extern void CodeGen_InitCompiler(); extern void CodeGen_TermCompiler(); extern void CodeGen_InitBackEndOptions(); extern void CodeGen_UpdateOptimizerOptions(); extern void CodeGen_UpdateBackEndOptions(); extern void MWUnmangle(const char *name, char *buf, int size); -extern COpts copts; +//extern COpts copts; extern CParams *cparamblkptr; extern FuncArg elipsis; extern FuncArg oldstyle; -extern HashNameNode *constructor_name_node; -extern HashNameNode *destructor_name_node; -extern char *CMangler_GetOperator(HashNameNode *str); extern jmp_buf errorreturn; extern Boolean cprep_nomem_exit; extern Boolean anyerrors; @@ -794,17 +321,7 @@ extern Boolean fatalerrors; extern SInt32 lines; extern char string[256]; extern TemplStack *ctempl_curinstance; -typedef struct ParserTryBlock { - struct ParserTryBlock *next; - jmp_buf jmpbuf; - NameSpace *cscope_current; - TypeClass *cscope_currentclass; - Object *cscope_currentfunc; - TemplStack *ctempl_curinstance; - TStreamElement *cerror_locktoken; - Boolean cscope_is_member_func; -} ParserTryBlock; -extern ParserTryBlock *trychain; +//extern ParserTryBlock *trychain; extern Boolean in_assembler; extern Boolean preprocessing_only; extern void AssemblerError(); @@ -817,14 +334,25 @@ extern short lookahead(); extern Object *CClass_Constructor(TypeClass *tclass); extern Object *CClass_Destructor(TypeClass *tclass); extern int CClass_CheckPures(TypeClass *tclass); +extern Boolean CClass_IsConstructor(Object *func); +extern short CABI_GetStructResultArgumentIndex(); +extern Boolean CParser_HasInternalLinkage(Object *obj); +extern HashNameNode *CParser_GetUniqueName(); +extern SInt32 CParser_GetUniqueID(); +extern Boolean CParserIsVolatileExpr(ENode *expr); +extern Boolean CParserIsConstExpr(ENode *expr); extern Boolean CParser_IsPublicRuntimeObject(Object *obj); extern Boolean CParser_ParseOperatorName(short *token, Boolean flag1, Boolean flag2); extern Boolean CTemplTool_EqualArgs(TemplArg *a, TemplArg *b); +extern Boolean CTemplTool_IsTemplateArgumentDependentType(Type *type); extern TypeTemplDep *CDecl_NewTemplDepType(TypeTemplDepType tdtype); +extern Type *CDecl_NewPointerType(Type *type); +extern Type *CDecl_NewStructType(SInt32 size, SInt32 align); +extern Type *CDecl_NewArrayType(Type *type, SInt32 num); extern GList name_mangle_list; extern void CPrep_UnLex(); extern Type *CTempl_ClassGetType(TypeClass *tclass); -extern short is_typesame(Type *t1, Type *t2); +//extern short is_typesame(Type *t1, Type *t2); extern Boolean is_unsigned(Type *type); extern void CDecl_CompleteType(Type *type); extern TemplArg *CTempl_ParseUncheckTemplArgs(void *fixmelater, Boolean flag); @@ -835,14 +363,95 @@ extern Boolean CParser_CheckTemplateClassUsage(TemplClass *tmclass, Boolean flag extern Type *CTempl_ParseTemplTemplParam(Type *t); extern void CClass_CheckPathAccess(BClassList *bcl, void *unk, AccessType access); extern BClassList *CClass_GetPathCopy(BClassList *path, Boolean flag); +extern Object *CClass_ThisSelfObject(); extern AccessType global_access; +extern HashNameNode *this_name_node; +extern void CParser_Setup(); +extern Boolean CParser_IsConst(Type *type, UInt32 qual); +extern void CParser_Cleanup(); +extern void SetupPrecompiler(Boolean flag); +extern void CleanupPrecompiler(); +extern void SetupAssembler(); +extern void CleanupAssembler(); +extern void ObjGen_Setup(); +extern void ObjGen_Finish(); +extern void ObjGen_Cleanup(); +extern void ObjGen_CodeCleanup(); +extern void ObjGen_DeclareFloatConst(Object *obj); +extern void ObjGen_DeclareVectorConst(Object *obj); +extern void ObjGen_DeclareCodeLabel(Object *labelobj, SInt32 offset, Object *funcobj); +extern Boolean ObjGen_IsExported(Object *obj); +extern void PointerAnalysis_Setup(); +extern void PointerAnalysis_Cleanup(); +extern Boolean CPrep_Preprocess(); +extern void cparser(); +extern void CBrowse_Setup(CParams *param); +extern void CBrowse_Finish(CParams *param); +extern void CBrowse_Cleanup(CParams *param); extern UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual); extern void CTemplClass_RegisterUsingDecl(TemplClass *tclass, Type *target, AccessType access); extern void CodeGen_InsertSpecialMacros(); -extern char *CodeGen_ExpandSpecialMacro(Macro *macro); extern void CPrep_PreprocessDumpFileInfo(Boolean flag); +extern void CPrep_PreprocessDumpNewLine(); extern Boolean gForceSourceLoc; extern void ObjGen_SegmentName(); // might take an arg, not sure since it's empty +extern void ObjGen_SrcBreakName(HashNameNode *name, SInt32 modDate, Boolean flag); +extern char *precomp_target_str; +extern Object *CParser_ParseObject(); +extern void PointerAnalysis_PragmaMode(); +extern void CExcept_Terminate(); +extern void CExcept_ArrayInit(); +extern void CExcept_Magic(); +extern void CSOM_PragmaReleaseOrder(); +extern void CSOM_PragmaClassVersion(); +extern void CSOM_PragmaMetaClass(); +extern void CSOM_PragmaCallStyle(); +extern short GetPrec(short t); +extern short localcount; +extern Boolean InlineAsm_gccmode; +extern void initialize_aliases(); +extern Statement *current_statement; +extern int pclist_bad_operand; +extern int n_real_registers[]; +extern short pic_base_reg; +extern Object pic_base; +extern ObjectList *exceptionlist; +extern ObjectList *arguments; +extern ObjectList *locals; +extern ObjectList *toclist; +extern Boolean uses_globals; +extern Boolean requires_frame; +extern void assign_locals_to_memory(ObjectList *locals); +extern PCodeLabel *pic_base_pcodelabel; +extern void *make_alias(Object *obj, SInt32 offset, SInt32 size); +extern Boolean is_volatile_object(Object *obj); +extern Boolean is_pascal_object(Object *obj); +extern Boolean local_is_16bit_offset(Object *obj); +extern Boolean can_add_displ_to_local(Object *obj, SInt32 displ); +extern int local_base_register(Object *obj); +extern int disable_optimizer; +extern Boolean IsTempName(HashNameNode *name); +extern void assign_local_memory(Object *obj); +extern void move_varargs_to_memory(); +extern Type stvoid; +extern TypePointer void_ptr; +extern int countexceptionactionregisters(ExceptionAction *exc); +extern void noteexceptionactionregisters(ExceptionAction *exc, PCodeArg *); +extern void recordexceptionactions(PCode *pc, ExceptionAction *exc); +extern SInt32 functionbodyoffset; +extern Object *CParser_NewRTFunc(Type *returntype, HashNameNode *name, Boolean unkflag, int argcount, ...); +extern SInt32 curstmtvalue; +extern Object *__memcpy_object; +extern void CInit_RewriteString(ENode *expr, Boolean flag); +extern int is_intrinsic_function_call(ENode *expr); +extern SInt32 I8_log2n(SInt64 value); +extern void PPCError_Error(int code); + +enum { + INTRINSIC_8 = 8, + INTRINSIC_35 = 35, + INTRINSIC_36 = 36 +}; enum { CPU_PPC401, @@ -875,6 +484,11 @@ enum { extern char *ScanFloat(char *input, double *output, Boolean *fail); +#define FITS_IN_SHORT(value) ( (value) == ((short) (value)) ) +// should HIGH_PART have (short) around it? +#define HIGH_PART(value) ( (((value) >> 16) + (((value) & 0x8000) >> 15)) ) +#define LOW_PART(value) ( (short) (value) ) + #ifdef __MWERKS__ #pragma options align=reset #endif diff --git a/includes/compiler/CABI.h b/includes/compiler/CABI.h new file mode 100644 index 0000000..fde5b21 --- /dev/null +++ b/includes/compiler/CABI.h @@ -0,0 +1,39 @@ +#ifndef COMPILER_CABI_H +#define COMPILER_CABI_H + +#include "compiler/common.h" +#include "compiler/CDecl.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +extern short CABI_GetStructResultArgumentIndex(void); +extern Type *CABI_GetSizeTType(void); +extern Type *CABI_GetPtrDiffTType(void); +extern SInt16 CABI_StructSizeAlignValue(Type *type, SInt32 size); +extern void CABI_ReverseBitField(TypeBitfield *tbitfield); +extern void CABI_AddVTable(TypeClass *tclass); +extern SInt32 CABI_GetVTableOffset(TypeClass *tclass); +extern void CABI_LayoutClass(DeclE *decle, TypeClass *tclass); +extern void CABI_MakeDefaultArgConstructor(Object *obj, TypeClass *tclass); +extern ENode *CABI_MakeThisExpr(TypeClass *tclass, SInt32 offset); +extern SInt32 CABI_GetCtorOffsetOffset(TypeClass *tclass, TypeClass *base); +extern Object *CABI_ConstructorCallsNew(TypeClass *tclass); +typedef Statement *(*TransConstructorCallback)(Statement *stmt, TypeClass *tclass, TypeClass *base, SInt32 offset, Boolean flag); +extern void CABI_TransConstructor(Object *obj, Statement *stmt, TypeClass *tclass, TransConstructorCallback callback, Boolean flag); +extern void CABI_MakeDefaultConstructor(TypeClass *tclass, Object *obj); +extern void CABI_MakeDefaultCopyConstructor(TypeClass *tclass, Object *obj); +extern void CABI_MakeDefaultAssignmentOperator(TypeClass *tclass, Object *obj); +extern void CABI_TransDestructor(Object *obj1, Object *obj2, Statement *stmt, TypeClass *tclass); +extern void CABI_MakeDefaultDestructor(TypeClass *tclass, Object *obj); +extern void CABI_MakeLayeredDestructor(TypeClass *tclass, Object *obj); +extern Object *CABI_GetDestructorObject(Object *obj, int what); +extern void CABI_AddLayeredDestructors(TypeClass *tclass); +extern ENode *CABI_DestroyObject(Object *dtor, ENode *objexpr, UInt8 mode, Boolean flag1, Boolean flag2); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CClass.h b/includes/compiler/CClass.h new file mode 100644 index 0000000..edefa92 --- /dev/null +++ b/includes/compiler/CClass.h @@ -0,0 +1,71 @@ +#ifndef COMPILER_CCLASS_H +#define COMPILER_CCLASS_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct VTableObjectLink { + struct VTableObjectLink *next; + Object *methodobj; + SInt32 offset; + SInt32 xC; +} VTableObjectLink; + +extern void CClass_Init(void); +extern void CClass_GenThunks(void); +extern UInt8 CClass_GetOverrideKind(TypeFunc *a, TypeFunc *b, Boolean errorflag); +extern Boolean CClass_IsEmpty(TypeClass *tclass); +extern Boolean CClass_IsNonStaticMemberFunc(TypeMethod *tmethod); +extern Object *CClass_DefaultConstructor(TypeClass *tclass); +extern Object *CClass_DummyDefaultConstructor(TypeClass *tclass); +extern ENode *CClass_DefaultConstructorCall(TypeClass *a, TypeClass *b, ENode *expr, SInt32 unkshortparam, Boolean flag1, Boolean flag2, Boolean *errorflag); +extern Object *CClass_AssignmentOperator(TypeClass *tclass); +extern Object *CClass_CopyConstructor(TypeClass *tclass); +extern NameSpaceObjectList *CClass_MemberObject(TypeClass *tclass, HashNameNode *name); +extern Object *CClass_Constructor(TypeClass *tclass); +extern Object *CClass_Destructor(TypeClass *tclass); +extern Boolean CClass_IsConstructor(Object *obj); +extern Boolean CClass_IsDestructor(Object *obj); +extern Boolean CClass_IsPODClass(TypeClass *tclass); +extern Boolean CClass_IsTrivialCopyClass(TypeClass *tclass); +extern Boolean CClass_IsTrivialCopyAssignClass(TypeClass *tclass); +extern Boolean CClass_ReferenceArgument(TypeClass *tclass); +extern BClassList *CClass_GetPathCopy(BClassList *path, Boolean is_global); +extern BClassList *CClass_AppendPath(BClassList *a, BClassList *b); +extern Boolean CClass_IsMoreAccessiblePath(BClassList *path1, BClassList *path2); +extern BClassList *CClass_GetBasePath(TypeClass *a, TypeClass *b, short *founddepth, Boolean *isambigbase); +extern Boolean CClass_IsBaseClass(TypeClass *a, TypeClass *b, short *founddepth, Boolean pathcheckflag, Boolean ambigerrorflag); +extern TypeClass *CClass_GetQualifiedClass(void); +extern ENode *CClass_AccessPathCast(BClassList *path, ENode *expr, Boolean flag); +extern ENode *CClass_ClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean ambigerrorflag, Boolean pathcheckflag); +extern ENode *CClass_DirectBasePointerCast(ENode *expr, TypeClass *a, TypeClass *b); +extern SInt32 CClass_GetPathOffset(BClassList *path); +extern Boolean CClass_ClassDominates(TypeClass *a, TypeClass *b); +extern SInt32 CClass_VirtualBaseOffset(TypeClass *a, TypeClass *b); +extern SInt32 CClass_VirtualBaseVTableOffset(TypeClass *a, TypeClass *b); +extern SInt32 CClass_GetMemberOffset(TypeClass *tclass, HashNameNode *name, ObjMemberVar **obj); +extern Boolean CClass_OverridesBaseMember(TypeClass *tclass, HashNameNode *name, Object *obj); +extern void CClass_DefineCovariantFuncs(Object *method, CI_FuncData *ifuncdata); +extern void CClass_CheckOverrides(TypeClass *tclass); +extern void CClass_ClassDefaultFuncAction(TypeClass *tclass); +extern void CClass_ClassAction(TypeClass *tclass); +extern void CClass_MakeStaticActionClass(TypeClass *tclass); +extern Object *CClass_CheckPures(TypeClass *tclass); +extern void CClass_MemberDef(Object *obj, TypeClass *tclass); +extern Object *CClass_ThisSelfObject(void); +extern ENode *CClass_CreateThisSelfExpr(void); +extern void CClass_CheckPathAccess(BClassList *path, Object *obj, AccessType access); +extern void CClass_CheckStaticAccess(BClassList *path, TypeClass *tclass, AccessType access); +extern void CClass_CheckObjectAccess(BClassList *path, Object *obj); +extern void CClass_CheckEnumAccess(BClassList *path, ObjEnumConst *objec); +extern Type *CClass_CombineClassAccessQualifiers(Type *type, UInt32 qual1, UInt32 qual2, UInt32 *outflags); +extern ENode *CClass_AccessMember(ENode *classexpr, Type *type, UInt32 qual, SInt32 offset); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CDecl.h b/includes/compiler/CDecl.h new file mode 100644 index 0000000..eda8669 --- /dev/null +++ b/includes/compiler/CDecl.h @@ -0,0 +1,127 @@ +#ifndef COMPILER_CDECL_H +#define COMPILER_CDECL_H + +#include "compiler/common.h" +#include "compiler/tokens.h" +#include "compiler/types.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +// named because it's 0xE bytes big (hurr) +typedef struct DeclE { + ObjBase **objlist; + void *x4; + unsigned short x8; + unsigned short xA; + Boolean xC; +} DeclE; + +struct DeclInfo { + Type *thetype; + UInt32 qual; + NameSpace *nspace; + HashNameNode *name; + Object *x10; + NameSpaceObjectList *x14; + void *x18; + void *x1C; + Type *x20; + ENode *x24; + TemplClass *x28; + TemplArg *expltargs; + void *x30; + void *x34; + void *x38; + Boolean x3C; + Boolean x3D; + short x3E; + short storageclass; + UInt8 section; + UInt8 exportflags; + Boolean x44; + Boolean x45; + Boolean x46; + Boolean x47; + Boolean x48; + Boolean x49; + Boolean x4A; + Boolean x4B; + Boolean x4C; + Boolean x4D; + Boolean x4E; + Boolean x4F; + Boolean x50; + Boolean x51; + Boolean has_expltargs; + Boolean x53; + Boolean x54; + Boolean x55; + Boolean x56; + Boolean x57; + FileOffsetInfo fileoffsetinfo; +}; + +typedef struct BigDeclInfo { + DeclInfo declinfo; + DeclInfo declinfo2; + Boolean xCC; + Boolean xCD; +} BigDeclInfo; + +extern AccessType global_access; +extern FileOffsetInfo member_fileoffset; + +extern Type *CDecl_NewStructType(SInt32 size, SInt16 align); +extern Type *CDecl_NewArrayType(Type *type, SInt32 size); +extern Type *CDecl_NewPointerType(Type *type); +extern Type *CDecl_NewRefPointerType(Type *type); +extern Type *CDecl_NewTemplDepType(TypeTemplDepType tdt); +extern void CDecl_SetResultReg(TypeFunc *tfunc); +extern void CDecl_SetFuncFlags(TypeFunc *tfunc, UInt32 flags); +extern void CDecl_NewConvFuncType(DeclInfo *declinfo); +extern void CDecl_CompleteType(Type *type); +extern Boolean IsCompleteType(Type *type); +extern Boolean CanAllocObject(Type *type); +extern Boolean CanCreateObject(Type *type); +extern void makethetypepointer(DeclInfo *declinfo, UInt32 qual); +extern void CDecl_AddThisPointerArgument(TypeFunc *tfunc, TypeClass *tclass); +extern void CDecl_MakePTMFuncType(TypeFunc *tfunc); +extern void CDecl_AddArgument(TypeFunc *tfunc, Type *argtype); +extern Boolean CDecl_CheckArrayIntegr(Type *type); +extern void CDecl_ParseDirectFuncDecl(DeclInfo *declinfo); +extern void makememberpointertype(DeclInfo *declinfo, TypeClass *tclass, UInt32 qual); +extern void CDecl_ScanPointer(DeclInfo *declinfo, NameSpace *nspace, Boolean flag); +extern void scandeclarator(DeclInfo *declinfo); +extern void conversion_type_name(DeclInfo *declinfo); +extern void MergeDefaultArgs(FuncArg *a, FuncArg *b); +extern void CheckDefaultArgs(FuncArg *args); +extern Object *CDecl_GetFunctionObject(DeclInfo *declinfo, NameSpace *nspace, Boolean *pflag, Boolean someotherflag); +extern void CDecl_TypedefDeclarator(DeclInfo *declinfo); +extern Boolean CDecl_FunctionDeclarator(DeclInfo *declinfo, NameSpace *nspace, Boolean flag, Boolean flag2); +extern void CDecl_ScanDeclarator(DeclInfo *declinfo); +extern void scandeclaratorlist(DeclInfo *declinfo); +extern void CDecl_ComputeUnderlyingEnumType(TypeEnum *tenum); +extern void scanenum(DeclInfo *declinfo); +extern void CDecl_ScanStructDeclarator(BigDeclInfo *bde); +extern void scanstruct(DeclInfo *declinfo, short structtype); +extern void CDecl_ExtractClassExportFlags(DeclInfo *declinfo, UInt8 flags); +extern TypeMethod *CDecl_MakeTypeMemberFunc(TypeFunc *tfunc, TypeClass *tclass, Boolean flag); +extern void CDecl_PackDeclInfo(PackedDeclInfo *packed, DeclInfo *declinfo); +extern void CDecl_UnpackDeclInfo(DeclInfo *declinfo, PackedDeclInfo *packed); +extern void CDecl_AddFriend(TypeClass *tclass, Object *friendfunc, TypeClass *friendclass); +extern void CDecl_CheckCtorIntegrity(FuncArg *args, TypeClass *tclass); +extern void CDecl_MakeVBaseList(TypeClass *tclass); +extern Boolean CDecl_CheckNewBase(TypeClass *a, TypeClass *b, Boolean flag); +extern TypeMethod *CDecl_MakeDefaultDtorType(TypeClass *tclass, Boolean is_virtual); +extern void CDecl_CompleteClass(DeclE *decle, TypeClass *tclass); +extern TypeClass *CDecl_DefineClass(NameSpace *nspace, HashNameNode *name, TypeClass *tclass, short mode, Boolean flag2, Boolean flag3); +extern void CDecl_ParseClassDeclSpec(UInt8 *declspec); +extern void CDecl_ParseClass(DeclInfo *declinfo, short mode, Boolean flag1, UInt8 class_declspec); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CError.h b/includes/compiler/CError.h index 89f67e4..dbe80c0 100644 --- a/includes/compiler/CError.h +++ b/includes/compiler/CError.h @@ -311,6 +311,11 @@ typedef struct _CErrorBuffer { UInt32 remaining; } CErrorBuffer; +extern TStreamElement *cerror_locktoken; +extern char cerror_synchdata[32]; +extern short cerror_synchoffset; +extern int CError_BreakPointcount; + extern void CError_Init(); extern void CError_SetErrorToken(TStreamElement *token); extern void CError_SetNullErrorToken(); @@ -354,7 +359,7 @@ extern void CError_OverloadedFunctionError(Object *obj, ObjectList *olst); extern void CError_AbstractClassError(TypeClass *tclass); extern void CError_Warning(int code, ...); extern void CError_BreakPoint(const char *a, const char *b); -extern void CError_Internal(); +extern void CError_Internal(char *filename, int line); extern void CError_ExpressionTooComplex(); extern void CError_NoMem(); extern void CError_UserBreak(); diff --git a/includes/compiler/CExpr.h b/includes/compiler/CExpr.h new file mode 100644 index 0000000..a82e56e --- /dev/null +++ b/includes/compiler/CExpr.h @@ -0,0 +1,237 @@ +#ifndef COMPILER_CEXPR_H +#define COMPILER_CEXPR_H + +#include "compiler/common.h" +#include "compiler/enode.h" +#include "compiler/types.h" +#include "compiler/CScope.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct ConIteratorList { + struct ConIteratorList *next; + struct ConIterator *iter; +} ConIteratorList; + +typedef struct ConIterator { + struct ConIterator *parent; + ConIteratorList *children; + TypeClass *tclass; +} ConIterator; + +typedef struct ConversionIterator { + CScopeObjectIterator objiter; + ConIterator myconiter; + ConIterator *coniter; +} ConversionIterator; + +enum { + CheckResult0, + CheckResult1, + CheckResult2, + CheckResult3, + CheckResult4 +}; + +// Rename me to StdMatch? +typedef struct Match5 { + short x0; + short x2; + short x4; + short x6; + short x8; +} Match5; + +typedef struct Match13 { + short x0; + short x2; + short x4; + short x6; + short x8; + short xA; + short xC; + short xE; + Match5 match5; +} Match13; + +// CExpr.c +extern Boolean (*name_obj_check)(void *, Object *); // TODO figure out the right type +extern Boolean disallowgreaterthan; + +// CExpr2.c +extern ENode *assign_node; +extern Boolean temp_reference_init; + +// CExpr.c +extern void CExpr_RewriteConst(); +extern void optimizecomm(ENode *expr); +extern short canadd(ENode *expr, SInt32 value); +extern ENode *checkreference(ENode *expr); +extern ENode *pointer_generation(ENode *expr); +extern void CExpr_PointerGeneration(); +extern void oldassignmentpromotion(); +extern ENode *argumentpromotion(ENode *expr, Type *type, short qual, Boolean flag); +extern ENode *classargument(ENode *expr); +extern ENodeList *CExpr_ScanExpressionList(Boolean flag); +extern void CExpr_DoExplicitConversion(); +extern void CExpr_MakeNameLookupResultExpr(); +extern void scansizeof(); +extern void scanalignof(); +extern ENode *getnodeaddress(ENode *expr, Boolean flag); +extern void getpointertomemberfunc(); +extern void CExpr_New_ELOGNOT_Node(); +extern void CExpr_New_EMONMIN_Node(); +extern void CExpr_New_EBINNOT_Node(); +extern ENode *unary_expression(void); +extern ENode *do_castnullcheck(ENode *a, ENode *b); +extern void CExpr_SafeClassPointerCast(); +extern ENode *PointerToMemberCast(ENode *expr, TypeMemberPointer *tm1, TypeMemberPointer *tm2, Boolean flag); +extern void CExpr_MemberPointerConversion(); +extern ENode *do_typecast(ENode *expr, Type *type, UInt32 qual); +extern void cast_expression(); +extern void CExpr_New_EMUL_Node(); +extern void CExpr_New_EDIV_Node(); +extern void CExpr_New_EMODULO_Node(); +extern void CExpr_New_EADD_Node(); +extern void CExpr_New_ESUB_Node(); +extern void CExpr_New_ESHL_Node(); +extern void CExpr_New_ESHR_Node(); +extern void CExpr_New_ELESS_Node(); +extern void CExpr_New_ELESSEQU_Node(); +extern void CExpr_New_EGREATER_Node(); +extern void CExpr_New_EGREATEREQU_Node(); +extern ENode *memberpointercompare(ENodeType t, ENode *left, ENode *right); +extern void CExpr_New_EEQU_Node(); +extern void CExpr_New_ENOTEQU_Node(); +extern void CExpr_New_EAND_Node(); +extern void CExpr_New_EXOR_Node(); +extern void CExpr_New_EOR_Node(); +extern void CExpr_New_ELAND_Node(); +extern void CExpr_New_ELOR_Node(); +extern void CExpr_NewDyadicNode(); +extern void CExpr_New_ECOND_Node(); +extern ENode *assignment_expression(void); +extern ENode *conv_assignment_expression(void); +extern void CExpr_CheckUnusedExpression(); +extern void s_expression(); +extern ENode *expression(void); +extern CInt64 CExpr_IntegralConstExprType(Type **tint); +extern ENode *CExpr_IntegralConstOrDepExpr(void); +extern CInt64 CExpr_IntegralConstExpr(void); +extern void CExpr_CheckUnwantedAssignment(); +extern void CExpr_ParseAsmExpr(); + +// CExpr2.c +typedef void (*CExprSearchCB)(ENode *expr); +typedef ENode *(*CExprReplaceCB)(ENode *expr); + +extern void CExpr_SearchExprTree(ENode *expr, CExprSearchCB callback, int count, ...); +extern ENode *CExpr_SearchExprTreeReplace(ENode *expr, CExprReplaceCB callback, int count, ...); +extern Boolean CExpr_HasFuncCall(ENode *expr); +extern void CExpr_AliasTransform(ENode *expr); +extern ENode *CExpr_UnaryFloatExpression(ENode *expr); +extern ENode *CExpr_BinaryFloatExpression(ENode *expr); +extern ENode *CExpr_NewENode(ENodeType ty); +extern ENode *CExpr_NewTemplDepENode(TemplDepSubType t); +extern ENode *nullnode(void); +extern ENode *intconstnode(Type *type, SInt32 value); +extern ENode *stringconstnode(char *str); +extern ENode *forceintegral(ENode *expr); +extern ENode *makemonadicnode(ENode *inner, ENodeType ty); +extern ENode *makediadicnode(ENode *left, ENode *right, ENodeType ty); +extern ENode *makecommaexpression(ENode *left, ENode *right); +extern short iszero(ENode *expr); +extern short isnotzero(ENode *expr); +extern Boolean CExpr_IsOne(ENode *expr); +extern Boolean CExpr_AllBitsSet(ENode *expr); +extern ENode *CExpr_NewETEMPNode(Type *type, Boolean assign_id); +extern ENode *CExpr_GetETEMPCopy(ENode *expr); +extern ENode *integralpromote(ENode *expr); +extern CInt64 CExpr_IntConstConvert(Type *a, Type *b, CInt64 val); +extern ENode *promote(ENode *expr, Type *type); +extern void CExpr_ArithmeticConversion(ENode **left, ENode **right); +extern ENode *CExpr_TempModifyExpr(ENode *expr); +extern Boolean CExpr_IsLValue(ENode *expr); +extern ENode *CExpr_LValue(ENode *expr, Boolean flag1, Boolean flag2); +extern ENode *CExpr_MakeObjRefNode(Object *obj, Boolean flag); +extern ENode *create_objectrefnode(Object *obj); +extern ENode *create_objectnode2(Object *obj); +extern ENode *create_objectnode(Object *obj); +extern ENode *CExpr_IsTempConstruction(ENode *expr, Type *type, ENode **resultexpr); +extern ENode *CExpr_AdjustFunctionCall(ENode *expr); +extern ENode *funccallexpr(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4); +extern ENode *CExpr_FuncCallSix(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4, ENode *arg5, ENode *arg6); +extern void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match); +extern Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match); +extern ENode *CExpr_ClassPointerCast(BClassList *cls, ENode *expr, Boolean nullcheckflag); +extern ENode *CExpr_GetClassAccessNode(BClassList *a, BClassList *b, ENode *expr, Object *obj, AccessType access, Boolean flag); +extern ENode *CExpr_ConvertToBool(ENode *expr, Boolean flag); +extern void CExpr_ConversionIteratorInit(ConversionIterator *iter, TypeClass *tclass); +extern Object *CExpr_ConversionIteratorNext(ConversionIterator *iter); +extern void user_assign_check(); +extern ENode *CExpr_ConvertToCondition(ENode *expr); +extern void CExpr_ConvertToIntegral(); +extern void CExpr_CheckArithmConversion(); +extern void get_address_of_temp_copy(); +extern short assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3); +extern void CExpr_MatchCompare(); +extern void CExpr_GetFuncMatchArgs(); +extern ENode *CExpr_GetDefaultArgument(ENode *funcexpr, FuncArg *arg); +extern ENode *CExpr_VarArgPromotion(ENode *expr, Boolean flag); +extern void CExpr_GenericFuncCall(); +extern void CExpr_GenericPtmfCall(); +extern void CExpr_MakeFunctionCall(); +extern void CExpr_CheckOperatorConversion(); +extern void CExpr_CheckOperator(); +extern ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *args, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4, Boolean flag5); +extern void scannew(); +extern void scandelete(); + +// CExprConvMatch.c +// static void CExpr_GetImplictObjectParamType(); +// static void CExpr_GetParamType(); +// static void CExpr_HasNParams(); +// static void CExpr_TypeCompare(); +// static void CExpr_IsReferenceCompatible(); +// static void CExpr_IsBaseOf(); +// static void CExpr_IsBetterClassConversion(); +// static void CExpr_IsBetterStandardConv(); +// static void CExpr_IsBetterImplicitConv(); +// static void CExpr_SetupStandardConversionResult(); +// static void CExpr_SetQualConversionResult(); +// static void CExpr_OverloadFuncMatch(); +// static void CExpr_StandardConversionMatch(); +// static void CExpr_UserConversion(); +// static void CExpr_UserConversionMatch(); +// static void CExpr_ImplicitConversionMatch(); +extern Boolean CExpr_CanImplicitlyConvert(ENode *expr, Type *type, UInt32 qual); +// static void CExpr_DerivedToBase(); +// static void CExpr_ClassReferenceConversion(); +// static void CExpr_BindToReference(); +extern ENode *CExpr_Convert(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2); +extern ENode *CExpr_AssignmentPromotion(ENode *expr, Type *type, UInt32 qual, Boolean flag); +// static void CExpr_IsBetterMatch(); +// static void CExpr_MatchArgs(); +// static void CExpr_GetMatchObject(); +// static void CExpr_FindBestMatch(); +extern void CExpr_FuncArgMatch(); +// static void CExpr_BuildConversionTypeList(); +// static void CExpr_NextPromotedIntegralType(); +// static void CExpr_NextArithmeticType(); +// static void CExpr_NextPromotedArithmeticType(); +// static void CExpr_MatchBuiltin(); +// static void CExpr_CheckIncDecBuiltin(); +// static void CExpr_CheckUnaryBuiltin(); +// static void CExpr_CheckBinaryBuiltin(); +// static void CExpr_MatchOperands(); +extern void CExpr_CondOperatorMatch(); +extern void CExpr_OperatorMatch(); +// static void CExpr_ClassCopyInit(); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CFunc.h b/includes/compiler/CFunc.h new file mode 100644 index 0000000..2247e5e --- /dev/null +++ b/includes/compiler/CFunc.h @@ -0,0 +1,147 @@ +#ifndef COMPILER_CFUNC_H +#define COMPILER_CFUNC_H + +#include "compiler/common.h" +#include "compiler/CScope.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct DeclBlock { + struct DeclBlock *next; + ExceptionAction *dobjstack; // is type right? + NameSpace *parent_nspace; + short index; +} DeclBlock; + +struct CLabel { + CLabel *next; + Statement *stmt; + HashNameNode *uniquename; + HashNameNode *name; + PCodeLabel *pclabel; + //void *sicg_label; +}; + +typedef enum StatementType { + ST_NOP = 1, + ST_LABEL, + ST_GOTO, + ST_EXPRESSION, + ST_SWITCH, + ST_IFGOTO, + ST_IFNGOTO, + ST_RETURN, + ST_OVF, + ST_EXIT, + ST_ENTRY, + ST_BEGINCATCH, + ST_ENDCATCH, + ST_ENDCATCHDTOR, + ST_GOTOEXPR, + ST_ASM, + ST_BEGINLOOP, + ST_ENDLOOP, + ST_ILLEGAL +} StatementType; + +enum { + StmtFlag_1 = 1 +}; + +struct Statement { + Statement *next; + StatementType type; + char marked; + UInt8 flags; + UInt16 value; + ENode *expr; + CLabel *label; + ExceptionAction *dobjstack; + SInt32 sourceoffset; + HashNameNode *sourcefilepath; +}; + +typedef struct InitExpr { + struct InitExpr *next; + ENode *expr; + Object *object; +} InitExpr; + +typedef struct CtorChain { + struct CtorChain *next; + UInt8 what; + ENode *objexpr; + union { + ClassList *base; // 0 + VClassList *vbase; // 1 + ObjMemberVar *membervar; // 2 + } u; +} CtorChain; + +typedef struct CFuncSave { + CScopeSave scope; + // lots of fields +} CFuncSave; + +struct DeclThing { + Type *thetype; + UInt32 qual; + NameSpace *nspace; + CLabel *xC; + CLabel *x10; +}; + +extern FuncArg elipsis; +extern FuncArg oldstyle; +extern ObjectList *arguments; +extern ObjectList *locals; +extern short localcount; +extern SInt32 curstmtvalue; +extern SInt32 sourceoffset; +extern HashNameNode *sourcefilepath; +extern SInt32 functionbodyoffset; +extern HashNameNode *functionbodypath; +extern InitExpr *init_expressions; +extern CLabel *Labels; +extern CtorChain *ctor_chain; +extern Statement *curstmt; + +extern DeclBlock *CFunc_NewDeclBlock(void); +extern void CFunc_RestoreBlock(DeclBlock *block); +extern void CFunc_SetupLocalVarInfo(Object *obj); +extern void CFunc_DefaultArg(Type *type, short qual, FuncArg *args); +extern Boolean CFunc_ParseFakeArgList(Boolean flag); +extern FuncArg *parameter_type_list(DeclInfo *declinfo); +extern CLabel *findlabel(void); +extern CLabel *newlabel(void); +extern Statement *CFunc_AppendStatement(StatementType sttype); +extern Statement *CFunc_InsertStatement(StatementType sttype, Statement *after); +extern Statement *CFunc_InsertBeforeStatement(StatementType sttype, Statement *before); +extern void CheckCLabels(void); +extern Object *create_temp_object(Type *type); +extern ENode *create_temp_node(Type *type); +extern ENode *create_temp_node2(Type *type); +extern void CFunc_WarnUnused(void); +extern void CFunc_CodeCleanup(Statement *stmt); +extern void CFunc_DestructorCleanup(Statement *stmt); +extern Statement *CFunc_GenerateLoop(Statement *stmt, Type *type, ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, ENode (*callback)(ENode *, ENode *)); +extern void CFunc_CompoundStatement(DeclThing *thing); +extern void CFunc_SetupNewFuncArgs(Object *obj, FuncArg *args); +extern NameSpace *CFunc_FuncGenSetup(Statement *stmt); +extern void CFunc_GetGlobalCompilerState(CFuncSave *state); +extern void CFunc_SetGlobalCompilerState(CFuncSave *state); +extern void CFunc_Gen(Statement *stmt, Object *obj, UInt8 unk); +extern void CFunc_CheckClassCtors(TypeClass *tclass); +extern void CFunc_ParseFuncDef(Object *obj, DeclInfo *declinfo, TypeClass *tclass, Boolean is_method, Boolean is_static, NameSpace *nspace); +extern void InitExpr_Register(ENode *expr, Object *object); +extern void CFunc_GenerateDummyFunction(Object *a); +extern void CFunc_GenerateSingleExprFunc(Object *a, ENode *expr); +extern void CFunc_GenerateDummyCtorFunc(Object *a, Object *b); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CInit.h b/includes/compiler/CInit.h new file mode 100644 index 0000000..9b1c24b --- /dev/null +++ b/includes/compiler/CInit.h @@ -0,0 +1,77 @@ +#ifndef COMPILER_CINIT_H +#define COMPILER_CINIT_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef void (*ExprCB)(Type *type, ENode *expr, Boolean flag); +typedef void (*InitExprRegisterCB)(ENode *expr); +typedef void (*InsertExprCB)(ENode *expr); +// fix last arg +typedef ENode *(*RegisterObjectCB)(Type *type, Object *obj, SInt32 offset, void *); +typedef ENode *(*TempNodeCB)(Type *type, Boolean flag); + +typedef struct OLinkList { + struct OLinkList *next; + Object *obj; + SInt32 offset; + SInt32 somevalue; +} OLinkList; + +typedef struct PooledString { + struct PooledString *next; + Object *obj; + int offset; + char *data; + SInt32 size; + Boolean ispascal; + Boolean iswide; +} PooledString; + +typedef struct InitInfo { + Object *obj; + OLinkList *list; + void *x8; + SInt32 expr_offset; + ExprCB expr_cb; + Boolean expr_cb_called; + Boolean x15; + Boolean x16; + InitExprRegisterCB init_expr_register_cb; + Object *obj1C; + InsertExprCB insert_expr_cb; + RegisterObjectCB register_object_cb; + char *buffer; + SInt32 size; + SInt32 bufferSize; + struct InitInfo *next; +} InitInfo; + +extern TempNodeCB cinit_tempnodefunc; +extern InitInfo *cinit_initinfo; + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern void CInit_Init(void); +extern Boolean CInit_RelocInitCheck(ENode *expr, Object **objptr, CInt64 *valptr, Boolean flag); +extern void CInit_ExportConst(Object *obj); +extern Statement *CInit_ConstructClassArray(Statement *stmt, TypeClass *tclass, Object *ctor, Object *dtor, ENode *firstarg, SInt32 count); +extern ENode *CInit_AutoObject(Object *obj, Type *type, UInt32 qual); +extern void CInit_InitializeAutoData(Object *obj, InsertExprCB insert_cb, RegisterObjectCB register_cb); +extern void CInit_InitializeStaticData(Object *obj, InitExprRegisterCB cb); +extern void CInit_InitializeData(Object *obj); +extern Object *CInit_DeclareString(char *data, SInt32 size, Boolean ispascal, Boolean iswide); +extern PooledString *CInit_DeclarePooledString(char *data, SInt32 size, Boolean ispascal); +extern PooledString *CInit_DeclarePooledWString(char *data, SInt32 size); +extern void CInit_RewriteString(ENode *expr, Boolean flag); +extern void CInit_DeclarePooledStrings(void); +extern void CInit_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size); +extern void CInit_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size); +extern void CInit_DefineTentativeData(void); + +#endif diff --git a/includes/compiler/CInline.h b/includes/compiler/CInline.h new file mode 100644 index 0000000..1b5abd5 --- /dev/null +++ b/includes/compiler/CInline.h @@ -0,0 +1,121 @@ +#ifndef COMPILER_CINLINE_H +#define COMPILER_CINLINE_H + +#include "compiler/common.h" +#include "compiler/tokens.h" +#include "compiler/CFunc.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct CI_Var { + HashNameNode *name; + Type *type; + UInt32 qual; + UInt8 sflags; + UInt8 xD; + UInt8 xE; +} CI_Var; + +typedef struct CI_Switch { + int fix_me; +} CI_Switch; + +typedef struct CI_Statement { + StatementType type; + UInt8 flags; + UInt16 value; + SInt32 sourceoffset; + HashNameNode *sourcefilepath; + ExceptionAction *dobjstack; + union { + SInt16 statementnum; + ENode *expr; + struct { + ENode *expr; + SInt16 statementnum; + } ifgoto; + CI_Switch *switchdata; + // TODO: Figure out the one for Inline ASM + } u; +} CI_Statement; + +struct CI_FuncData { + short numarguments; + CI_Var *arguments; + short numlocals; + CI_Var *locals; + short numstatements; + CI_Statement *statements; + FileOffsetInfo fileoffset; + SInt32 symdecloffset; + SInt32 functionbodyoffset; + HashNameNode *functionbodypath; + SInt32 symdeclend; + Boolean can_inline; +}; + +typedef enum { + CI_ActionInlineFunc = 0, + CI_ActionMemberFunc = 1, + CI_ActionTemplateFunc = 2, + CI_ActionDefaultFunc = 3 +} CI_ActionType; + +typedef struct CI_Action { + struct CI_Action *next; + Object *obj; + union { + struct { + FileOffsetInfo fileoffset; + TStream stream; + TypeClass *tclass; + CI_ActionType actiontype; + } inlinefunc; + struct { + Type *a; + Type *b; + TemplateMember *tmemb; + } memberfunc; + struct { + TemplateFunction *func; + TemplFuncInstance *inst; + } templatefunc; + } u; +} CI_Action; + +typedef enum { + CopyMode0, + CopyMode1, + CopyMode2, + CopyMode3, + CopyMode4 +} CInlineCopyMode; + +extern CI_Action *cinline_tactionlist; + +extern void CInline_Init(void); +extern SInt32 CInline_GetLocalID(Object *obj); +extern Boolean CInline_ExpressionHasSideEffect(ENode *expr); +extern ENode *CInline_CopyExpression(ENode *expr, CInlineCopyMode mode); +extern void CInline_SerializeStatement(Statement *stmt); +extern Object *CInline_GetLocalObj(SInt32 id, Boolean flag); +extern SInt32 CInline_GetStatementNumber(Statement *first, Statement *stmt); +extern void CInline_PackIFunctionData(CI_FuncData *packed, Statement *stmt, Object *obj); +extern void CInline_UnpackIFunctionData(Object *obj, CI_FuncData *packed, Statement *stmt); +extern void CInline_AddDefaultFunctionAction(Object *obj); +extern void CInline_AddInlineFunctionAction(Object *obj, TypeClass *tclass, FileOffsetInfo *fileoffset, TStream *stream, Boolean flag); +extern void CInline_AddMemberFunctionAction(Object *obj, Type *a, Type *b, TemplateMember *tmemb); +extern void CInline_AddTemplateFunctionAction(Object *obj, TemplateFunction *func, TemplFuncInstance *inst); +extern void CInline_ObjectAddrRef(Object *obj); +extern void CInline_GenFunc(Statement *stmt, Object *obj, UInt8 unk); +extern Boolean CInline_CanFreeLHeap(void); +extern Boolean CInline_GenerateDeferredFuncs(void); +extern void CInline_Finish(void); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CInt64.h b/includes/compiler/CInt64.h index 455bf3f..7986a4a 100644 --- a/includes/compiler/CInt64.h +++ b/includes/compiler/CInt64.h @@ -13,6 +13,10 @@ extern const CInt64 cint64_min; inline int CInt64_IsNegative(const CInt64 *n) { return (n->hi & 0x80000000) != 0; } +inline UInt32 CInt64_GetULong(const CInt64 *n) { // 42E660 in mwcppc.exe + return n->lo; + +} inline void CInt64_SetLong(CInt64 *pN, SInt32 n) { pN->lo = n; pN->hi = (n < 0) ? 0xFFFFFFFF : 0; @@ -22,7 +26,7 @@ inline void CInt64_SetULong(CInt64 *pN, UInt32 n) { pN->hi = 0; } -inline int CInt64_IsZero(CInt64 *n) { +inline Boolean CInt64_IsZero(CInt64 *n) { //if (n->hi == 0 && n->lo == 0) // return 1; //else diff --git a/includes/compiler/CMachine.h b/includes/compiler/CMachine.h new file mode 100644 index 0000000..a4bc1a5 --- /dev/null +++ b/includes/compiler/CMachine.h @@ -0,0 +1,84 @@ +#ifndef COMPILER_CMACHINE_H +#define COMPILER_CMACHINE_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +extern TypeIntegral stbool; +extern TypeIntegral stchar; +extern TypeIntegral stsignedchar; +extern TypeIntegral stunsignedchar; +extern TypeIntegral stwchar; +extern TypeIntegral stsignedshort; +extern TypeIntegral stunsignedshort; +extern TypeIntegral stsignedint; +extern TypeIntegral stunsignedint; +extern TypeIntegral stsignedlong; +extern TypeIntegral stunsignedlong; +extern TypeIntegral stsignedlonglong; +extern TypeIntegral stunsignedlonglong; +extern TypeIntegral stfloat; +extern TypeIntegral stshortdouble; +extern TypeIntegral stdouble; +extern TypeIntegral stlongdouble; + +extern TypeStruct stvectorunsignedchar; +extern TypeStruct stvectorsignedchar; +extern TypeStruct stvectorboolchar; +extern TypeStruct stvectorunsignedshort; +extern TypeStruct stvectorsignedshort; +extern TypeStruct stvectorboolshort; +extern TypeStruct stvectorunsignedlong; +extern TypeStruct stvectorsignedlong; +extern TypeStruct stvectorboollong; +extern TypeStruct stvectorfloat; +extern TypeStruct stvectorpixel; +extern TypeStruct stvector; + +extern void CMach_Configure(void); +extern SInt32 CMach_GetQUALalign(UInt32 qual); +extern SInt32 CMach_ArgumentAlignment(Type *type); +extern SInt32 CMach_AllocationAlignment(Type *type, UInt32 qual); +extern CInt64 CMach_CalcIntDiadic(Type *type, CInt64 left, short op, CInt64 right); +extern CInt64 CMach_CalcIntMonadic(Type *type, short op, CInt64 val); +extern CInt64 CMach_CalcIntConvertFromFloat(Type *type, Float fval); +extern void CMach_InitIntMem(Type *type, CInt64 val, void *mem); +extern void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem, Boolean flag); +extern Float CMach_CalcFloatDiadic(Type *type, Float left, short op, Float right); +extern Float CMach_CalcFloatMonadic(Type *type, short op, Float fval); +extern Boolean CMach_CalcFloatDiadicBool(Type *type, Float left, short op, Float right); +extern Boolean CMach_CalcVectorDiadicBool(Type *type, MWVector128 *left, short op, MWVector128 *right); +extern char *CMach_FloatScan(char *input, Float *result, Boolean *fail); +extern Float CMach_CalcFloatConvertFromInt(Type *type, CInt64 val); +extern Float CMach_CalcFloatConvert(Type *type, Float fval); +extern Boolean CMach_FloatIsZero(Float fval); +extern Boolean CMach_FloatIsOne(Float fval); +extern Boolean CMach_FloatIsNegOne(Float fval); +extern void CMach_InitFloatMem(Type *type, Float val, void *mem); +extern void CMach_PrintFloat(char *buf, Float val); +extern void CMach_PragmaParams(void); +extern void CMach_AdjustFuntionArgs(void); +extern SInt16 CMach_GetStructAlign(TypeStruct *tstruct); +extern SInt16 CMach_GetClassAlign(TypeClass *tclass); +extern SInt16 CMach_GetTypeAlign(Type *type); +extern SInt16 CMach_MemberAlignValue(Type *type, SInt32 var); +extern void CMach_StructLayoutInitOffset(SInt32 offset); +extern SInt32 CMach_StructLayoutGetCurSize(void); +extern SInt32 CMach_StructLayoutGetOffset(Type *type, UInt32 qual); +extern SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual); +extern UInt8 CMach_GetFunctionResultClass(TypeFunc *tfunc); +extern Boolean CMach_PassResultInHiddenArg(Type *type); +extern const char *CMach_GetCPU(void); +extern Boolean CMach_FloatIsPowerOf2(Float flt); +extern Float CMach_FloatReciprocal(Float flt); +extern SInt32 CMach_RoundedSizeOf(Object *object); +extern void CMach_ReInitRuntimeObjects(void); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CMangler.h b/includes/compiler/CMangler.h new file mode 100644 index 0000000..f08ecd8 --- /dev/null +++ b/includes/compiler/CMangler.h @@ -0,0 +1,35 @@ +#ifndef COMPILER_CMANGLER_H +#define COMPILER_CMANGLER_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +extern HashNameNode *constructor_name_node; +extern HashNameNode *destructor_name_node; +extern HashNameNode *asop_name_node; + +extern void CMangler_Setup(void); +extern HashNameNode *CMangler_BasicDtorName(void); +extern HashNameNode *CMangler_VBaseDtorName(void); +extern HashNameNode *CMangler_ArrayDtorName(void); +extern HashNameNode *CMangler_SDeleteDtorName(void); +extern HashNameNode *CMangler_DeleteDtorName(void); +extern char *CMangler_GetOperator(HashNameNode *opname); +extern HashNameNode *CMangler_OperatorName(short token); +extern HashNameNode *CMangler_VTableName(TypeClass *tclass); +extern HashNameNode *CMangler_RTTIObjectName(Type *type, UInt32 qual); +extern HashNameNode *CMangler_ThunkName(Object *obj, int a, int b, int c); +extern HashNameNode *CMangler_TemplateInstanceName(HashNameNode *basename, TemplArg *args); +extern void CMangler_MangleType(Type *type, UInt32 qual); +extern HashNameNode *CMangler_ConversionFuncName(Type *type, UInt32 qual); +extern HashNameNode *CMangler_GetCovariantFunctionName(Object *obj, Type *type); +extern HashNameNode *CMangler_GetLinkName(Object *obj); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CParser.h b/includes/compiler/CParser.h new file mode 100644 index 0000000..21a3d59 --- /dev/null +++ b/includes/compiler/CParser.h @@ -0,0 +1,385 @@ +#ifndef COMPILER_CPARSER_H +#define COMPILER_CPARSER_H + +#include "compiler/common.h" +#include "compiler/enode.h" +#include "compiler/tokens.h" +#include "compiler/types.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +enum { + AlignMode0_Mac68k, + AlignMode1_Mac68k4byte, + AlignMode2_PPC, + AlignMode3_1Byte, + AlignMode4_2Byte, + AlignMode5_4Byte, + AlignMode6_8Byte, + AlignMode7_16Byte, + AlignMode8_Packed +}; + +// not sure how many of these are char and how many are unsigned char or Boolean +typedef struct COpts { + Boolean little_endian; + Boolean codegen_dynamic; + Boolean codegen_pic; + Boolean no_common; + char no_implicit_templates; + char absolutepath; // determines the path written to debug info + char x06; // linker/objgen related + short cpu; + char schedule_cpu; + unsigned char schedule_mode; // may be an enum?? + SInt32 debuglisting; + char profile; + char traceback; + Boolean disable_registers; + char fp_contract; + Boolean no_register_save_helpers; + char ppc_unroll_speculative; + short ppc_unroll_instructions_limit; + short ppc_unroll_factor_limit; + Boolean altivec_model; + UInt8 x1B; // altivec/vrsave related + UInt8 code_alignment; + char x1D; + UInt8 x1E; // some register used in TOC_use_isel + UInt8 gen_fsel; + char ppc_opt_bclr_bcctr; + Boolean use_lmw_stmw; + char report_heap_info; + char misaligned_mem_access; + char switch_tables; + char prepare_compress; + char some_alignment; // used in CMach_AllocationAlignment + Boolean asmsemicolcomment; + Boolean asmpoundcomment; + StringPtr oldprefixname; + short inlinelevel; + int inline_max_size; + int inline_max_total_size; + char inline_bottom_up; + Boolean cplusplus; + Boolean ecplusplus; + Boolean objective_c; + char objc_strict; + Boolean ARM_conform; + char ARM_scoping; + Boolean require_prototypes; + Boolean trigraphs; + Boolean only_std_keywords; + Boolean enumsalwaysint; + Boolean ANSI_strict; + Boolean mpwc_relax; + Boolean mpwc_newline; + Boolean ignore_oldstyle; + Boolean cpp_extensions; + Boolean pointercast_lvalue; + char useRTTI; + char delete_exception; + char _4B; + Boolean oldalignment; + Boolean unsignedchars; + Boolean multibyteaware; + char autoinline; + char defer_codegen; + Boolean direct_to_som; + char som_env_check; + char som_call_opt; + Boolean booltruefalse; + char old_enum_mangler; + Boolean longlong; + Boolean longlong_enums; + char no_tfuncinline; + char _59; + Boolean flat_include; + char syspath_once; + Boolean always_import; + char simple_class_byval; + Boolean wchar_type; + Boolean vbase_ctor_offset; + char vbase_abi_v2; + Boolean def_inherited; + char template_patch; + char template_friends; + char faster_pch_gen; + Boolean array_new_delete; + Boolean dollar_identifiers; + char def_inline_tfuncs; + char arg_dep_lookup; + Boolean simple_prepdump; + char line_prepdump; + char fullpath_prepdump; + char old_mtemplparser; + char suppress_init_code; + Boolean reverse_bitfields; + Boolean c9x; + Boolean float_constants; + Boolean no_static_dtors; + Boolean longlong_prepeval; + Boolean const_strings; + char dumpir; + char experimental; + Boolean gcc_extensions; + char stdc_fp_contract; + char stdc_fenv_access; + char stdc_cx_limitedr; + Boolean old_argmatch; + char optEH; + char optEH2; + Boolean new_mangler; + char microsoft; + Boolean warningerrors; + Boolean pedantic; + char check_header_flags; + Boolean supress_warnings; + Boolean warn_illpragma; + Boolean warn_emptydecl; + char warn_possunwant; + char warn_unusedvar; + char warn_unusedarg; + Boolean warn_extracomma; + char warn_hidevirtual; + Boolean warn_largeargs; + char warn_implicitconv; + char warn_notinlined; + Boolean warn_structclass; + Boolean warn_padding; + char warn_no_side_effect; + char warn_resultnotused; + char warn_ptr_int_conv; + char align_mode; + Boolean align_array_members; + Boolean dont_reuse_strings; + Boolean pool_strings; + Boolean explicit_zero_data; + Boolean readonly_strings; + Boolean exceptions; + char _99; + char dont_inline; + char always_inline; + Boolean peephole; + char global_optimizer; + char side_effects; + Boolean internal; + Boolean import; + Boolean export; + Boolean lib_export; + char nosyminline; + char force_active; + char optimizationlevel; + Boolean optimize_for_size; + char optimizewithasm; + Boolean crippled; + char opt_common_subs; + char opt_loop_invariants; + char opt_propagation; + char opt_dead_assignments; + char opt_strength_reduction; + char opt_strength_reduction_strict; + char opt_dead_code; + char opt_lifetimes; + char _B1; // unused? + char opt_unroll_loops; + char opt_vectorize_loops; + char _B4; // amount of IRO passes? + char opt_pointer_analysis; + char opt_pointer_analysis_mode; + char loop_unroll_count; + char loop_unroll_size_threshold; + Boolean isGeneratingDebugInfo; + CWDataType pchCreator; + CWDataType pchType; + CWDataType text; + HashNameNode *forcedSegment; // when set by #pragma segment +} COpts; + +typedef struct ParserTryBlock { + struct ParserTryBlock *next; + jmp_buf jmpbuf; + NameSpace *cscope_current; + TypeClass *cscope_currentclass; + Object *cscope_currentfunc; + TemplStack *ctempl_curinstance; + TStreamElement *cerror_locktoken; + Boolean cscope_is_member_func; +} ParserTryBlock; + +typedef struct CallbackAction { + struct CallbackAction *next; + Object *obj; + TypeClass *tclass; +} CallbackAction; + +extern FileOffsetInfo cparser_fileoffset; +extern TStreamElement symdecltoken; +extern ParserTryBlock *trychain; +extern Boolean inassembler; +extern Boolean dont_set_references; +extern TypeStruct ptmstruct; +extern TypeStruct catchinfostruct; +extern Boolean in_assembler; +extern Boolean illegalimplicitconversion; +extern Boolean in_func_arglist; +extern NameSpaceName *newp_fobj; +extern NameSpaceName *newa_fobj; +extern NameSpaceName *delp_fobj; +extern NameSpaceName *dela_fobj; +extern Object *newh_func; +extern Object *delh_func; +extern Object *copy_func; +extern Object *clear_func; +extern Object *Rgtid_func; +extern Object *Rdync_func; +extern Object *rt_ptmf_cast; +extern Object *rt_ptmf_cmpr; +extern Object *rt_ptmf_test; +extern Object *rt_ptmf_call; +extern Object *rt_ptmf_scall; +extern Object *rt_ptmf_call4; +extern Object *rt_ptmf_scall4; +extern Object *rt_ptmf_null; +extern Object *rt_som_new; +extern Object *rt_som_newcheck; +extern Object *rt_som_check; +extern Object *rt_som_glue1; +extern Object *rt_som_glue2; +extern Object *rt_som_glue3; +extern Object *carr_func; +extern Object *cnar_func; +extern Object *darr_func; +extern Object *dnar_func; +extern Object *dnar3_func; +extern Object *Xgreg_func; +extern Object *Xthrw_func; +extern Object *Xicth_func; +extern Object *Xecth_func; +extern Object *Xunex_func; +extern COpts copts; +extern struct GList name_mangle_list; +extern HashNameNode *no_name_node; +extern HashNameNode *temp_argument_name; +extern HashNameNode *this_name_node; +extern HashNameNode *self_name_node; +extern HashNameNode *vptr_name_node; +extern CallbackAction *callbackactions; +extern Boolean fatalerrors; +extern Boolean anyerrors; +extern jmp_buf errorreturn; +extern char string[256]; +extern SInt32 compilererrornum; +extern SInt32 compilererrfile; +extern SInt32 compilererrline; + +extern Type sttemplexpr; +extern Type stillegal; +extern Type stvoid; +extern TypePointer void_ptr; +extern TypeFunc rt_func; + +enum { + ATOM_VOID = 1, + ATOM_CHAR, + ATOM_UCHAR, + ATOM_WCHAR, + ATOM_SHORT, + ATOM_USHORT, + ATOM_INT, + ATOM_UINT, + ATOM_LONG, + ATOM_ULONG, + ATOM_LONGLONG, + ATOM_ULONGLONG, + ATOM_FLOAT, + ATOM_SHORTDOUBLE, + ATOM_DOUBLE, + ATOM_LONGDOUBLE +}; + +extern Object *CParser_NewRTFunc(Type *rettype, HashNameNode *name, Boolean flag, int argcount, ...); +extern Boolean CParser_IsPublicRuntimeObject(Object *obj); +extern Object *CParser_FindPublicRuntimeObject(HashNameNode *name); +extern Boolean CParser_ReInitRuntimeObjects(Boolean is_precompiler); +extern void CParser_Setup(void); +extern void CParser_Cleanup(void); +extern short GetPrec(short token); +extern Boolean CParser_ParseOperatorName(short *token, Boolean flag1, Boolean flag2); +extern SInt32 CParser_GetUniqueID(void); +extern void CParser_PrintUniqueID(char *buf); +extern void CParser_SetUniqueID(SInt32 id); +extern HashNameNode *CParser_GetUniqueName(void); +extern HashNameNode *CParser_NameConcat(char *a, char *b); +extern HashNameNode *CParser_AppendUniqueName(char *prefix); +extern HashNameNode *CParser_AppendUniqueNameFile(char *prefix); +extern Boolean IsTempName(HashNameNode *name); +extern void CParser_UpdateObject(Object *object, DeclInfo *declinfo); +extern Object *CParser_NewObject(DeclInfo *declinfo); +extern Object *CParser_NewLocalDataObject(DeclInfo *declinfo, Boolean add_to_locals); +extern Object *CParser_NewGlobalDataObject(DeclInfo *declinfo); +extern Object *CParser_NewCompilerDefDataObject(void); +extern Object *CParser_NewFunctionObject(DeclInfo *declinfo); +extern Object *CParser_NewCompilerDefFunctionObject(void); +extern Object *CParser_NewAliasObject(Object *object, SInt32 offset); +extern FuncArg *CParser_NewFuncArg(void); +extern Type *atomtype(void); +extern Object *CParser_FindDeallocationObject(Type *type, FuncArg *args, Boolean flag1, Boolean flag2, Boolean *outflag); +extern short is_memberpointerequal(Type *a, Type *b); +extern short is_typeequal(Type *a, Type *b); +extern short iscpp_typeequal(Type *a, Type *b); +extern short CParser_CompareArgLists(FuncArg *a, FuncArg *b); +extern Boolean is_arglistsame(FuncArg *a, FuncArg *b); +extern short is_typesame(Type *a, Type *b); +extern Type *CParser_GetBoolType(void); +extern Type *CParser_GetWCharType(void); +extern short CParser_GetOperator(ENodeType t); +extern Boolean CParser_IsMoreCVQualified(UInt32 a, UInt32 b); +extern Boolean CParser_IsSameOrMoreCVQualified(UInt32 a, UInt32 b); +extern Boolean is_unsigned(Type *type); +extern StructMember *ismember(TypeStruct *tstruct, HashNameNode *name); +extern void appendmember(TypeStruct *tstruct, StructMember *member); +extern Boolean isdeclaration(UInt8 flag1, UInt8 flag2, UInt8 flag3, short token); +extern Boolean islookaheaddeclaration(void); +extern Type *CParser_ParseTypeID(UInt32 *qual, Boolean *flag); +extern Boolean CParser_TryFuncDecl(void); +extern Boolean CParser_TryParamList(Boolean flag); +extern Type *CParser_RemoveTopMostQualifiers(Type *type, UInt32 *qual); +extern UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual); +extern UInt32 CParser_GetCVTypeQualifiers(Type *type, UInt32 qual); +extern Boolean CParser_IsConst(Type *type, UInt32 qual); +extern Boolean CParser_IsVolatile(Type *type, UInt32 qual); +extern Boolean is_const_object(Object *obj); +extern Boolean is_volatile_object(Object *obj); +extern Boolean CParserIsConstExpr(ENode *expr); +extern Boolean CParserIsVolatileExpr(ENode *expr); +extern Boolean CParser_HasInternalLinkage(Object *obj); +extern Boolean CParser_HasInternalLinkage2(Object *obj); +extern Boolean CParser_IsVirtualFunction(Object *obj, TypeClass **tclass, SInt32 *index); +extern Boolean is_pascal_object(Object *obj); +extern Boolean is_cfm_type(Type *type); +extern Boolean CParser_IsVTableObject(Object *obj); +extern void TypedefDeclInfo(DeclInfo *declinfo, Type *type, UInt32 qual); +extern void CParser_ParseAttribute(Type *type, DeclInfo *declinfo); +extern void CParser_ParseDeclSpec(DeclInfo *declinfo, Boolean flag); +extern Boolean CParser_CheckTemplateClassUsage(TemplClass *tmclass, Boolean flag); +extern void CParser_GetDeclSpecs(DeclInfo *di, Boolean flag); +extern void CParser_RegisterNonGlobalClass(TypeClass *tclass); +extern void CParser_RegisterSingleExprFunction(Object *func, ENode *expr); +extern void CParser_RegisterDummyCtorFunction(Object *func, Object *obj); +extern Boolean CParser_IsAnonymousUnion(DeclInfo *di, Boolean flag); +extern void CParser_CheckAnonymousUnion(DeclInfo *di, Boolean flag); +extern void CParser_NewCallBackAction(Object *obj, TypeClass *tclass); +extern void CParser_NewClassAction(TypeClass *tclass); +extern void CParser_CallBackAction(Object *obj); +extern Object *CParser_ParseObject(void); +extern void CParser_ParseGlobalDeclaration(void); +extern void cparser(void); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CPrep.h b/includes/compiler/CPrep.h new file mode 100644 index 0000000..a681ec5 --- /dev/null +++ b/includes/compiler/CPrep.h @@ -0,0 +1,122 @@ +#ifndef COMPILER_CPREP_H +#define COMPILER_CPREP_H + +#include "compiler/common.h" +#include "compiler/tokens.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct Macro { + struct Macro *next; + HashNameNode *name; + void *c; + unsigned short xC; + Boolean is_special; + Boolean xF; + void *e; +} Macro; +typedef struct TokenStack { + char *pos; + char *macrostart; + Macro *macro; + Boolean macrocheck; +} TokenStack; + +extern CParams *cparamblkptr; +extern short tk; +extern CInt64 tkintconst; +extern Float tkfloatconst; +extern char *tkstring; +extern HashNameNode *tkidentifier; +extern SInt32 tksize; +extern short ispascalstring; +extern short nlflag; +extern SInt32 lines; +extern Boolean spaceskip; +extern struct Macro **macrohashtable; +extern Boolean cprep_nomem_exit; +extern Boolean cprep_nostring; +extern Boolean cprep_eoltokens; +extern TokenStack tokenstack[128]; +extern short tokenstacklevel; +extern CPrepFileInfo *cprep_cursymfile; +extern char *pos; +extern char *macropos; +extern char *nextcharpos; +extern unsigned char CPrep_SkipNewCommentChar; +extern Boolean preprocessing_only; +extern Handle stringmem; +extern SInt32 maxstringsize; +extern char cprep_idarray[256]; +extern Boolean was_escchar; +extern Boolean macrocheck; +extern Boolean widestring; +extern Boolean at_linestart; +extern char *prep_file_start; +extern char *prep_file_end; +extern char *macrostart; +extern Boolean cprep_strconcat; +extern CPrepFileInfo *prep_file; +extern short filesp; +extern SInt32 linenumber; +extern struct GList pplist; +extern TStreamElement *ts_current; +extern SInt32 ts_preread_elements; + +extern void CPrep_InsertSpecialMacro(Macro *macro, char *name); +extern void CPrep_InsertSpecialMacros(void); +extern void CPrep_RemoveSpecialMacros(void); +extern Boolean setupprep(void); +extern void cleanupprep(void); +extern void CPrep_TSBufferGrow(int amount); +extern void CPrep_TokenStreamGetState(SInt32 *state); +extern void CPrep_TokenStreamSetState(SInt32 *state); +extern void CPrep_UnLex(void); +extern void CPrep_TokenStreamSetCurState(SInt32 *state); +typedef void (*CPrepStreamFuncPtr)(TStreamElement *); +extern void CPrep_StreamGetBlock(TStream *stream, CPrepStreamFuncPtr func, int arg); +extern void CPrep_StreamGetSemicolon(TStream *stream, CPrepStreamFuncPtr func); +extern void CPrep_StreamGetTemplate(TStream *stream, CPrepStreamFuncPtr func); +extern void CPrep_StreamInsert(TStream *stream, SInt32 *state); +extern void CPrep_StreamRemove(TStream *stream, SInt32 *state); +extern void CPrep_RemoveTokens(SInt32 amount); +extern void CPrep_TokenStreamFlush(void); +extern TStreamElement *CPrep_CurStreamElement(void); +extern void CPrep_GetTokenContext(TStreamElement *token, CPrepFileInfo **tokenfile, SInt32 *selectionoffset, short *tokensize, SInt32 *linenumber, char *buf1, short *tokenoffset, short *tokenlength, char *buf2, short *lastarg); +extern void CPrep_Error(short code); +extern void CPrep_ErrorName(short code, const char *name); +extern void CPrep_Warning(short code); +extern void CPrep_WarningName(short code, const char *name); +extern void CPrep_ErrorMessage(int errTable, char *str, Boolean flag1, Boolean flag2); +extern void CPrep_ErrorMessageVA(int code, const char *format, va_list list, Boolean flag1, Boolean flag2); +extern void popfile(void); +extern void CPrep_SetSourceFile(FileOffsetInfo *foi); +extern HashNameNode *CPrep_GetSourceFilePath(CPrepFileInfo *fileinfo); +extern void CPrep_NewFileOffsetInfo(FileOffsetInfo *foi, TStreamElement *ts); +extern SInt32 CPrep_GetFileOffsetInfo(FileOffsetInfo *foi); +extern void CPrep_GetFileOffsetInfo2(FileOffsetInfo *foi, SInt32 *pLine, HashNameNode **pName); +extern void CPrep_ResetFileInfo(FileOffsetInfo *foi); +extern void CPrep_GetPrepPos(CPrepFileInfo **file, SInt32 *ppos); +extern UInt8 C_Compiler(CParams *param); +extern void poptokenseq(void); +extern void foundnl(void); +extern void newline(void); +extern short notendofline(void); +extern char *CPrep_GetFileName(char *buffer, Boolean flag1, Boolean flag2); +extern Boolean macrotest(void); +extern short CPrep_PragmaLex(Boolean no_err); +extern void CPrep_PushOption(SInt32 id, char value); +extern void CPrep_PopOption(SInt32 id); +extern void preprocessor(void); +extern SInt32 CPrep_BrowserTokenOffset(FileOffsetInfo *foi); +extern SInt32 CPrep_BrowserFileOffset(void); +extern void CPrep_BrowserFilePosition(CPrepFileInfo **fileinfo, SInt32 *offset); +extern CPrepFileInfo *CPrep_BrowserCurrentFile(void); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CPrepTokenizer.h b/includes/compiler/CPrepTokenizer.h new file mode 100644 index 0000000..f65cff6 --- /dev/null +++ b/includes/compiler/CPrepTokenizer.h @@ -0,0 +1,32 @@ +#ifndef COMPILER_CPREPTOKENIZER_H +#define COMPILER_CPREPTOKENIZER_H + +#include "compiler/common.h" +#include "compiler/tokens.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +extern short prepskipnextchar(void); +extern short prepnextchar(void); +extern short prepnextstringchar(char *str, Boolean flag); +extern void CPrep_MatchChar(char ch, Boolean flag); +extern char *CPrep_MatchChar2(char *start, char ch, Boolean flag); +extern short prepcurchar(void); +extern char *ReadIdentifier(char *p); +extern char *CPrep_SkipNewComment(char *str); +extern Boolean skipendoflinematch(char *str, short token); +extern void skipendofline(void); +extern void CPrep_SkipAsmComment(void); +extern short lookahead(void); +extern short lookahead_noeol(void); +extern short lex(void); +extern short plex(void); +extern short lexidentifier(void); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CScope.h b/includes/compiler/CScope.h new file mode 100644 index 0000000..95266b1 --- /dev/null +++ b/includes/compiler/CScope.h @@ -0,0 +1,107 @@ +#ifndef COMPILER_CSCOPE_H +#define COMPILER_CSCOPE_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +extern Boolean cscope_is_member_func; +extern Object *cscope_currentfunc; +extern TypeClass *cscope_currentclass; +extern NameSpace *cscope_current; +extern NameSpace *cscope_root; + +typedef struct CScopeSave { + NameSpace *current; + TypeClass *currentclass; + Object *currentfunc; + Boolean is_member_func; +} CScopeSave; // assumed name + +typedef struct CScopeParseResult { + NameSpace *nspace_0; + HashNameNode *name_4; + Type *x8; + UInt32 xC; // qual + ObjBase *obj_10; + NameSpaceObjectList *nsol_14; + BClassList *bcl_18; + Boolean x1C; + Boolean x1D; + Boolean isambig; + Boolean x1F; + Boolean x20; + Boolean x21; +} CScopeParseResult; + +typedef struct CScopeNSIterator { + NameSpace *nspace; + NameSpaceLookupList *lookup; + CScopeParseResult *result; +} CScopeNSIterator; + +typedef struct CScopeObjectIterator { + NameSpace *nspace; + NameSpaceName *nextname; + NameSpaceObjectList *currlist; + int hashindex; +} CScopeObjectIterator; + +extern void CScope_Setup(void); +extern void CScope_Cleanup(void); +extern void CScope_GetScope(CScopeSave *save); +extern void CScope_SetNameSpaceScope(NameSpace *nspace, CScopeSave *save); +extern void CScope_SetClassScope(TypeClass *cls, CScopeSave *save); +extern void CScope_SetClassDefScope(TypeClass *cls, CScopeSave *save); +extern void CScope_SetFunctionScope(Object *function, CScopeSave *save); +extern void CScope_SetMethodScope(Object *function, TypeClass *cls, Boolean unknownFlag, CScopeSave *save); +extern void CScope_RestoreScope(CScopeSave *saved); +extern Boolean CScope_IsEmptySymTable(void); +extern Boolean CScope_IsInLocalNameSpace(NameSpace *nspace); +extern NameSpaceObjectList *CScope_FindName(NameSpace *nspace, HashNameNode *name); +extern NameSpaceName *CScope_FindNameSpaceName(NameSpace *nspace, HashNameNode *name); +extern NameSpaceObjectList *CScope_InsertName(NameSpace *nspace, HashNameNode *name); +extern NameSpaceObjectList *CScope_ArgumentDependentNameLookup(NameSpaceObjectList *list, HashNameNode *name, ENodeList *argNodes, Boolean flag); +extern NameSpace *CScope_NewHashNameSpace(HashNameNode *name); +extern NameSpace *CScope_NewListNameSpace(HashNameNode *name, Boolean is_global); +extern NameSpace *CScope_FindNonClassNonFunctionNS(NameSpace *nspace); +extern NameSpace *CScope_FindGlobalNS(NameSpace *nspoce); +extern Boolean CScope_IsStdNameSpace(NameSpace *nspace); +extern Boolean CScope_IsEmptyNameSpace(NameSpace *nspace); +extern void CScope_MergeNameSpace(NameSpace *dst, NameSpace *src); +extern void CScope_AddObject(NameSpace *nspace, HashNameNode *name, ObjBase *obj); +extern void CScope_AddGlobalObject(Object *obj); +extern NameSpaceLookupList *CScope_BuildNameSpaceLookupList(NameSpace *nspace); +extern Boolean CScope_FindQualifiedClassMember(CScopeParseResult *result, TypeClass *tclass, HashNameNode *name); +extern Type *CScope_GetType(NameSpace *nspace, HashNameNode *name, UInt32 *qual); +extern Type *CScope_GetTagType(NameSpace *nspace, HashNameNode *name); +extern Boolean CScope_ParseExprName(CScopeParseResult *result); +extern Boolean CScope_ParseDeclName(CScopeParseResult *result); +extern Boolean CScope_ParseQualifiedNameSpace(CScopeParseResult *result, Boolean flag1, Boolean flag2); +extern Boolean CScope_ParseElaborateName(CScopeParseResult *result); +extern Boolean CScope_FindObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name); +extern Boolean CScope_FindNonClassObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name); +extern NameSpaceObjectList *CScope_FindObjectList(CScopeParseResult *result, HashNameNode *name); +extern Boolean CScope_PossibleTypeName(HashNameNode *name); +extern Boolean CScope_FindClassMemberObject(TypeClass *tclass, CScopeParseResult *result, HashNameNode *name); +extern void CScope_InitObjectIterator(CScopeObjectIterator *iterator, NameSpace *nspace); +extern ObjBase *CScope_NextObjectIteratorObject(CScopeObjectIterator *iterator); +extern NameSpaceObjectList *CScope_NextObjectIteratorObjectList(CScopeObjectIterator *iterator); +extern void CScope_DefineTypeTag(NameSpace *nspace, HashNameNode *name, Type *type); +extern Type *CScope_GetLocalTagType(NameSpace *nspace, HashNameNode *name); +extern Boolean CScope_FindTypeName(NameSpace *nspace, HashNameNode *name, CScopeParseResult *result); +extern NameSpaceObjectList *CScope_GetLocalObject(NameSpace *nspace, HashNameNode *name); +extern BClassList *CScope_GetClassAccessPath(BClassList *list, TypeClass *tclass); +extern Boolean CScope_ParseMemberName(TypeClass *tclass, CScopeParseResult *result, Boolean flag); +extern void CScope_AddClassUsingDeclaration(TypeClass *tclass, TypeClass *tclass2, HashNameNode *name, AccessType access); +extern void CScope_ParseUsingDeclaration(NameSpace *nspace, short access, Boolean flag); +extern void CScope_ParseNameSpaceAlias(HashNameNode *name); +extern void CScope_ParseUsingDirective(NameSpace *nspace); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/CodeGen.h b/includes/compiler/CodeGen.h new file mode 100644 index 0000000..3954d51 --- /dev/null +++ b/includes/compiler/CodeGen.h @@ -0,0 +1,79 @@ +#ifndef COMPILER_CODEGEN_H +#define COMPILER_CODEGEN_H + +#include "compiler/common.h" +#include "compiler/CPrep.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +extern Macro vecM; +extern Macro altivecM; +extern Object *gFunction; +extern PCodeLabel *returnlabel; +extern PCodeLabel *cleanreturnlabel; +extern Boolean needs_cleanup; +extern Statement *current_statement; +extern int has_catch_blocks; +extern int disable_optimizer; +extern SInt32 current_linenumber; +extern Boolean has_altivec_arrays; +extern short high_reg; +extern short low_reg; +extern short high_offset; +extern short low_offset; +extern short low_reg2; +extern short high_reg2; +extern PCodeLabel *pic_base_pcodelabel; +extern Object *dyld_stub_binding_helper; +extern Object *rt_cvt_fp2unsigned; +extern Object *rt_profile_entry; +extern Object *rt_profile_exit; +extern Object *rt_div2i; +extern Object *rt_div2u; +extern Object *rt_mod2i; +extern Object *rt_mod2u; +extern Object *rt_shr2i; +extern Object *rt_shr2u; +extern Object *rt_shl2i; +extern Object *rt_cvt_ull_dbl; +extern Object *rt_cvt_sll_dbl; +extern Object *rt_cvt_ull_flt; +extern Object *rt_cvt_sll_flt; +extern Object *rt_cvt_dbl_usll; + +extern VarInfo *CodeGen_GetNewVarInfo(void); +extern Object *maketemporary(Type *type); +typedef void (*ArgumentProcessor)(Object *obj, short reg); +extern void process_arguments(ArgumentProcessor func, Boolean flag); +extern void move_assigned_argument(Object *obj, short reg); +extern void assign_labels(); +extern void CodeGen_Generator(); +extern void CodeGen_GenVDispatchThunk(); +extern void CodeGen_SetupRuntimeObjects(); +extern Boolean CodeGen_ReInitRuntimeObjects(Boolean is_precompiler); +extern Boolean CodeGen_IsPublicRuntimeObject(Object *obj); +extern void CodeGen_SOMStub(); +extern void CodeGen_ParseDeclSpec(HashNameNode *identifier, DeclInfo *declinfo); +extern void CodeGen_ParsePragma(HashNameNode *name); +extern void CodeGen_UpdateObject(Object *object); +extern void CodeGen_UpdateBackEndOptions(); +extern void CodeGen_objc_method_self_offset(); +extern void CodeGen_objc_method_sel_offset(); +extern void CodeGen_objc_method_arg_offset(); +extern void CodeGen_objc_method_args_size(); +extern void CodeGen_HandleIntrinsicCall(); +extern void CodeGen_HandleTypeCast(); +extern short CodeGen_AssignCheck(ENode *expr, Type *type, Boolean flag1, Boolean flag2); +extern void CodeGen_CollapseVectorExpression(); +extern void CodeGen_InsertSpecialMacros(); +extern char *CodeGen_ExpandSpecialMacro(Macro *macro); +extern void CodeGen_reportheapinfo(); +extern void CodeGen_InitialSanityCheck(); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/Operands.h b/includes/compiler/Operands.h new file mode 100644 index 0000000..8c6aa93 --- /dev/null +++ b/includes/compiler/Operands.h @@ -0,0 +1,85 @@ +#ifndef COMPILER_OPERANDS_H +#define COMPILER_OPERANDS_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +extern Float one_point_zero; + +enum OperandType { + // Value in a register (identified by 'reg') + OpndType_GPR = 0, + // Uses 'reg', 'object, 'immOffset' + OpndType_GPR_ImmOffset = 1, + // Uses 'reg', 'regOffset' + OpndType_GPR_Indexed = 2, + // Value in two registers (identified by 'reg' and 'regHi') + OpndType_GPRPair = 3, + // Value at an absolute address (identified by 'abs_address') + OpndType_Absolute = 4, + // Value in a float register (identified by 'reg') + OpndType_FPR = 5, + // Value in a vector register (identified by 'reg') + OpndType_VR = 6, + // Condition value: 'reg' stores which condition register, and 'regOffset' is equal to ENOTEQU, EEQU, EGREATEREQU, + // ELESS, ELESS or ELESSEQU + OpndType_CRField = 7, + // Value of a symbol (identified by 'object') + OpndType_Symbol = 8, + // Reference to a location (at 'reg', offset using 'object' and 'immOffset') + OpndType_IndirectGPR_ImmOffset = 9, + // Reference to a location (at 'reg', offset using the value of register 'regOffset') + OpndType_IndirectGPR_Indexed = 0xA, + // Reference to a symbol (identified by 'object') + OpndType_IndirectSymbol = 0xB +}; + +// These are probably the same as the PCode Flags and can be unified? +enum { + OpndFlags_Const = 0x40, + OpndFlags_Volatile = 0x80 +}; + +struct Operand { + enum OperandType optype; + SInt16 reg; + SInt16 regHi; + SInt16 regOffset; + SInt32 immOffset; + SInt32 abs_address; + Object *object; + UInt32 flags; +}; + +extern void load_immediate(short reg, SInt32 value); +extern void symbol_operand(Operand *op, Object *obj); +extern void indirect(Operand *op, ENode *expr); +extern void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut); +extern void coerce_to_addressable(Operand *op); +extern void Coerce_to_register(Operand *op, Type *type, short output_reg); +extern void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short output_regHi); +extern void Coerce_to_fp_register(Operand *op, TypeIntegral *tint, short output_reg); +extern void Coerce_to_v_register(Operand *op, TypeStruct *tstruct, short output_reg); +extern void store(short reg, Operand *op, Type *type); +extern void store_pair(short reg, short regHi, Operand *op, Type *type); +extern void store_fp(short reg, Operand *op, TypeIntegral *tint); +extern void store_v(short reg, Operand *op, TypeStruct *tstruct); +extern void extend32(Operand *op, Type *type, short output_reg); +extern void extend64(Operand *op, Type *type, short output_reg, short output_regHi); +extern void load_floating_constant(short reg, TypeIntegral *type, double *data); +extern void convert_integer_to_floating(Operand *op, Boolean is_single, short output_reg); +extern void convert_unsigned_to_floating(Operand *op, Boolean is_single, short output_reg); +extern void convert_floating_to_integer(Operand *op, short output_reg); +extern void convert_floating_to_unsigned(Operand *op, short output_reg); +extern void extract_bitfield(Operand *input_op, TypeBitfield *tbitfield, short output_reg, Operand *output_op); +extern void insert_bitfield(short reg, Operand *op, TypeBitfield *tbitfield); +extern void load_address(short dest_reg, Operand *op); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/PCode.h b/includes/compiler/PCode.h new file mode 100644 index 0000000..55aac38 --- /dev/null +++ b/includes/compiler/PCode.h @@ -0,0 +1,194 @@ +#ifndef COMPILER_PCODE_H +#define COMPILER_PCODE_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +#define PCODE_FLAG_SET_T(pcode) (((pcode)->flags & (fPCodeFlag1 | fPCodeFlag8)) ? (pcode)->flags : 0) +#define PCODE_FLAG_SET_F(pcode) (((pcode)->flags & (fPCodeFlag1 | fPCodeFlag8)) ? 0 : (pcode)->flags) + +enum { + EffectRead = 1, + EffectWrite = 2 +}; + +typedef enum { + PCOp_REGISTER, + PCOp_SYSREG, + PCOp_IMMEDIATE, + PCOp_MEMORY, + PCOp_LABEL, + PCOp_LABELDIFF, + PCOp_PLACEHOLDEROPERAND +} PCOpKind; + +typedef enum { + RefType_0, + RefType_1, + RefType_2, + RefType_3, + RefType_4, + RefType_5, + RefType_6, + RefType_7, + RefType_8, + RefType_9, + RefType_A, + RefType_B, + RefType_C, + RefType_D +} PCRefType; + +struct PCodeArg { + PCOpKind kind; + char arg; + union { + struct { + unsigned short effect; + short reg; + } reg; + struct { + SInt32 value; + Object *obj; + } imm; + struct { + SInt32 offset; + Object *obj; + } mem; + struct { + PCodeLabel *label; + } label; + struct { + SInt16 offset; + PCodeLabel *labelA; + PCodeLabel *labelB; + } labeldiff; + unsigned char placeholder[10]; // keep the size + } data; +}; + +struct PCode { + PCode *nextPCode; + PCode *prevPCode; + PCodeBlock *block; + unsigned int xx_C; + unsigned int _10; + int flags; + void *_18; + SInt32 sourceoffset; + short op; + short argCount; + PCodeArg args[0]; +}; + +struct PCodeLabel { + PCodeLabel *nextLabel; + PCodeBlock *block; + short resolved; + short index; +}; + +typedef struct _PCLink { + struct _PCLink *nextLink; + struct PCodeBlock *block; +} PCLink; + +struct PCodeBlock { + struct PCodeBlock *nextBlock; + struct PCodeBlock *prevBlock; + PCodeLabel *labels; + PCLink *predecessors; + PCLink *successors; + PCode *firstPCode; + PCode *lastPCode; + int blockIndex; + int codeOffset; // in bytes + int loopWeight; + short pcodeCount; + unsigned short flags; +}; + +/* PCode Flags */ +enum { + fPCodeFlag1 = 1, + fPCodeFlag2 = 2, + fPCodeFlag4 = 4, + fPCodeFlag8 = 8, + fPCodeFlag10 = 0x10, + fPCodeFlag20 = 0x20, + // Always valid + fIsConst = 0x40, + fIsVolatile = 0x80, + fSideEffects = 0x100, + fPCodeFlag200 = 0x200, // ? + fPCodeFlag400 = 0x400, // ? + fPCodeFlag800 = 0x800, // ? + fPCodeFlag1000 = 0x1000, // ? + fCommutative = 0x2000, + fIsCSE = 0x4000, + fPCodeFlag8000 = 0x8000, + fPCodeFlag20000 = 0x20000, // ? + fPCodeFlag40000 = 0x40000, // ? + // Set 1 only + fLink = 0x1000000, + fBranchNotTaken = 0x4000000, + fBranchTaken = 0x8000000, + fAbsolute = 0x10000000, + // Set 2 only + fIsPtrOp = 0x20, + fOverflow = 0x800000, + fSetsCarry = 0x10000000, + // ?? + fPCodeFlag8000000 = 0x8000000, + fPCodeFlag10000000 = 0x10000000, + fPCodeFlag20000000 = 0x20000000, + fPCodeFlag40000000 = 0x40000000, + fPCodeFlag80000000 = 0x80000000 +}; + +enum { + fPCBlockFlag1 = 1, // prologue + fPCBlockFlag2 = 2, // epilogue + fPCBlockFlag4 = 4, + fPCBlockFlag8 = 8, + fPCBlockFlag10 = 0x10, + fPCBlockFlag20 = 0x20, + fPCBlockFlag4000 = 0x4000 +}; + +extern PCodeBlock *pcbasicblocks; +extern PCodeBlock *pclastblock; +extern PCodeBlock *prologue; +extern PCodeBlock *epilogue; +extern PCodeBlock **depthfirstordering; +extern int pcblockcount; +extern int pcloopweight; + +extern void initpcode(); +extern PCode *makepcode(short op, ...); +extern void emitpcode(short op, ...); +extern PCode *copypcode(PCode *pcode); +extern PCodeLabel *makepclabel(); +extern PCodeBlock *makepcblock(); +extern void pclabel(PCodeBlock *block, PCodeLabel *label); +extern void pcbranch(PCodeBlock *block, PCodeLabel *label); +extern void pccomputepredecessors(); +extern void deleteblock(PCodeBlock *block); +extern void deleteunreachableblocks(); +extern void appendpcode(PCodeBlock *block, PCode *pcode); +extern void deletepcode(PCode *pcode); +extern void insertpcodebefore(PCode *anchor, PCode *newpcode); +extern void insertpcodeafter(PCode *anchor, PCode *newpcode); +extern void setpcodeflags(int flags); +extern void clearpcodeflags(int flags); +extern int pccomputeoffsets(); +extern void computedepthfirstordering(); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/PCodeInfo.h b/includes/compiler/PCodeInfo.h new file mode 100644 index 0000000..137e10a --- /dev/null +++ b/includes/compiler/PCodeInfo.h @@ -0,0 +1,1335 @@ +#ifndef COMPILER_PCODEINFO_H +#define COMPILER_PCODEINFO_H + +#include "compiler/PCode.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct _OpcodeInfo { + const char *name; + const char *format; + unsigned char x8; + unsigned char x9; + int flags; + unsigned int insn; +} OpcodeInfo; + +/*enum { + PC_B = 0x0, + PC_BL = 0x1, + PC_BC = 0x2, + PC_BCLR = 0x3, + PC_BCCTR = 0x4, + PC_BT = 0x5, + PC_BTLR = 0x6, + PC_BTCTR = 0x7, + PC_BF = 0x8, + PC_BFLR = 0x9, + PC_BFCTR = 0xA, + PC_BDNZ = 0xB, + PC_BDNZT = 0xC, + PC_BDNZF = 0xD, + PC_BDZ = 0xE, + PC_BDZT = 0xF, + PC_BDZF = 0x10, + PC_BLR = 0x11, + PC_BCTR = 0x12, + PC_BCTRL = 0x13, + PC_BLRL = 0x14, + PC_LBZ = 0x15, + PC_LBZU = 0x16, + PC_LBZX = 0x17, + PC_LBZUX = 0x18, + PC_LHZ = 0x19, + PC_LHZU = 0x1A, + PC_LHZX = 0x1B, + PC_LHZUX = 0x1C, + PC_LHA = 0x1D, + PC_LHAU = 0x1E, + PC_LHAX = 0x1F, + PC_LHAUX = 0x20, + PC_LHBRX = 0x21, + PC_LWZ = 0x22, + PC_LWZU = 0x23, + PC_LWZX = 0x24, + PC_LWZUX = 0x25, + PC_LWBRX = 0x26, + PC_LMW = 0x27, + PC_STB = 0x28, + PC_STBU = 0x29, + PC_STBX = 0x2A, + PC_STBUX = 0x2B, + PC_STH = 0x2C, + PC_STHU = 0x2D, + PC_STHX = 0x2E, + PC_STHUX = 0x2F, + PC_STHBRX = 0x30, + PC_STW = 0x31, + PC_STWU = 0x32, + PC_STWX = 0x33, + PC_STWUX = 0x34, + PC_STWBRX = 0x35, + PC_STMW = 0x36, + PC_DCBF = 0x37, + PC_DCBST = 0x38, + PC_DCBT = 0x39, + PC_DCBTST = 0x3A, + PC_DCBZ = 0x3B, + PC_ADD = 0x3C, + PC_ADDC = 0x3D, + PC_ADDE = 0x3E, + PC_ADDI = 0x3F, + PC_ADDIC = 0x40, + PC_ADDICR = 0x41, + PC_ADDIS = 0x42, + PC_ADDME = 0x43, + PC_ADDZE = 0x44, + PC_DIVW = 0x45, + PC_DIVWU = 0x46, + PC_MULHW = 0x47, + PC_MULHWU = 0x48, + PC_MULLI = 0x49, + PC_MULLW = 0x4A, + PC_NEG = 0x4B, + PC_SUBF = 0x4C, + PC_SUBFC = 0x4D, + PC_SUBFE = 0x4E, + PC_SUBFIC = 0x4F, + PC_SUBFME = 0x50, + PC_SUBFZE = 0x51, + PC_CMPI = 0x52, + PC_CMP = 0x53, + PC_CMPLI = 0x54, + PC_CMPL = 0x55, + PC_ANDI = 0x56, + PC_ANDIS = 0x57, + PC_ORI = 0x58, + PC_ORIS = 0x59, + PC_XORI = 0x5A, + PC_XORIS = 0x5B, + PC_AND = 0x5C, + PC_OR = 0x5D, + PC_XOR = 0x5E, + PC_NAND = 0x5F, + PC_NOR = 0x60, + PC_EQV = 0x61, + PC_ANDC = 0x62, + PC_ORC = 0x63, + PC_EXTSB = 0x64, + PC_EXTSH = 0x65, + PC_CNTLZW = 0x66, + PC_RLWINM = 0x67, + PC_RLWNM = 0x68, + PC_RLWIMI = 0x69, + PC_SLW = 0x6A, + PC_SRW = 0x6B, + PC_SRAWI = 0x6C, + PC_SRAW = 0x6D, + PC_CRAND = 0x6E, + PC_CRANDC = 0x6F, + PC_CREQV = 0x70, + PC_CRNAND = 0x71, + PC_CRNOR = 0x72, + PC_CROR = 0x73, + PC_CRORC = 0x74, + PC_CRXOR = 0x75, + PC_MCRF = 0x76, + PC_MTXER = 0x77, + PC_MTCTR = 0x78, + PC_MTLR = 0x79, + PC_MTCRF = 0x7A, + PC_MTMSR = 0x7B, + PC_MTSPR = 0x7C, + PC_MFMSR = 0x7D, + PC_MFSPR = 0x7E, + PC_MFXER = 0x7F, + PC_MFCTR = 0x80, + PC_MFLR = 0x81, + PC_MFCR = 0x82, + PC_MFFS = 0x83, + PC_MTFSF = 0x84, + PC_EIEIO = 0x85, + PC_ISYNC = 0x86, + PC_SYNC = 0x87, + PC_RFI = 0x88, + PC_LI = 0x89, + PC_LIS = 0x8A, + PC_MR = 0x8B, + PC_NOP = 0x8C, + PC_NOT = 0x8D, + PC_LFS = 0x8E, + PC_LFSU = 0x8F, + PC_LFSX = 0x90, + PC_LFSUX = 0x91, + PC_LFD = 0x92, + PC_LFDU = 0x93, + PC_LFDX = 0x94, + PC_LFDUX = 0x95, + PC_STFS = 0x96, + PC_STFSU = 0x97, + PC_STFSX = 0x98, + PC_STFSUX = 0x99, + PC_STFD = 0x9A, + PC_STFDU = 0x9B, + PC_STFDX = 0x9C, + PC_STFDUX = 0x9D, + PC_FMR = 0x9E, + PC_FABS = 0x9F, + PC_FNEG = 0xA0, + PC_FNABS = 0xA1, + PC_FADD = 0xA2, + PC_FADDS = 0xA3, + PC_FSUB = 0xA4, + PC_FSUBS = 0xA5, + PC_FMUL = 0xA6, + PC_FMULS = 0xA7, + PC_FDIV = 0xA8, + PC_FDIVS = 0xA9, + PC_FMADD = 0xAA, + PC_FMADDS = 0xAB, + PC_FMSUB = 0xAC, + PC_FMSUBS = 0xAD, + PC_FNMADD = 0xAE, + PC_FNMADDS = 0xAF, + PC_FNMSUB = 0xB0, + PC_FNMSUBS = 0xB1, + PC_FRES = 0xB2, + PC_FRSQRTE = 0xB3, + PC_FSEL = 0xB4, + PC_FRSP = 0xB5, + PC_FCTIW = 0xB6, + PC_FCTIWZ = 0xB7, + PC_FCMPU = 0xB8, + PC_FCMPO = 0xB9, + PC_LWARX = 0xBA, + PC_LSWI = 0xBB, + PC_LSWX = 0xBC, + PC_STFIWX = 0xBD, + PC_STSWI = 0xBE, + PC_STSWX = 0xBF, + PC_STWCX = 0xC0, + PC_ECIWX = 0xC1, + PC_ECOWX = 0xC2, + PC_DCBI = 0xC3, + PC_ICBI = 0xC4, + PC_MCRFS = 0xC5, + PC_MCRXR = 0xC6, + PC_MFTB = 0xC7, + PC_MFSR = 0xC8, + PC_MTSR = 0xC9, + PC_MFSRIN = 0xCA, + PC_MTSRIN = 0xCB, + PC_MTFSB0 = 0xCC, + PC_MTFSB1 = 0xCD, + PC_MTFSFI = 0xCE, + PC_SC = 0xCF, + PC_FSQRT = 0xD0, + PC_FSQRTS = 0xD1, + PC_TLBIA = 0xD2, + PC_TLBIE = 0xD3, + PC_TLBLD = 0xD4, + PC_TLBLI = 0xD5, + PC_TLBSYNC = 0xD6, + PC_TW = 0xD7, + PC_TRAP = 0xD8, + PC_TWI = 0xD9, + PC_OPWORD = 0xDA, + PC_MFROM = 0xDB, + PC_DSA = 0xDC, + PC_ESA = 0xDD, + PC_DCCCI = 0xDE, + PC_DCREAD = 0xDF, + PC_ICBT = 0xE0, + PC_ICCCI = 0xE1, + PC_ICREAD = 0xE2, + PC_RFCI = 0xE3, + PC_TLBRE = 0xE4, + PC_TLBSX = 0xE5, + PC_TLBWE = 0xE6, + PC_WRTEE = 0xE7, + PC_WRTEEI = 0xE8, + PC_MFDCR = 0xE9, + PC_MTDCR = 0xEA, + PC_DCBA = 0xEB, + PC_DSS = 0xEC, + PC_DSSALL = 0xED, + PC_DST = 0xEE, + PC_DSTT = 0xEF, + PC_DSTST = 0xF0, + PC_DSTSTT = 0xF1, + PC_LVEBX = 0xF2, + PC_LVEHX = 0xF3, + PC_LVEWX = 0xF4, + PC_LVSL = 0xF5, + PC_LVSR = 0xF6, + PC_LVX = 0xF7, + PC_LVXL = 0xF8, + PC_STVEBX = 0xF9, + PC_STVEHX = 0xFA, + PC_STVEWX = 0xFB, + PC_STVX = 0xFC, + PC_STVXL = 0xFD, + PC_MFVSCR = 0xFE, + PC_MTVSCR = 0xFF, + PC_VADDCUW = 0x100, + PC_VADDFP = 0x101, + PC_VADDSBS = 0x102, + PC_VADDSHS = 0x103, + PC_VADDSWS = 0x104, + PC_VADDUBM = 0x105, + PC_VADDUBS = 0x106, + PC_VADDUHM = 0x107, + PC_VADDUHS = 0x108, + PC_VADDUWM = 0x109, + PC_VADDUWS = 0x10A, + PC_VAND = 0x10B, + PC_VANDC = 0x10C, + PC_VAVGSB = 0x10D, + PC_VAVGSH = 0x10E, + PC_VAVGSW = 0x10F, + PC_VAVGUB = 0x110, + PC_VAVGUH = 0x111, + PC_VAVGUW = 0x112, + PC_VCFSX = 0x113, + PC_VCFUX = 0x114, + PC_VCMPBFP = 0x115, + PC_VCMPEQFP = 0x116, + PC_VCMPEQUB = 0x117, + PC_VCMPEQUH = 0x118, + PC_VCMPEQUW = 0x119, + PC_VCMPGEFP = 0x11A, + PC_VCMPGTFP = 0x11B, + PC_VCMPGTSB = 0x11C, + PC_VCMPGTSH = 0x11D, + PC_VCMPGTSW = 0x11E, + PC_VCMPGTUB = 0x11F, + PC_VCMPGTUH = 0x120, + PC_VCMPGTUW = 0x121, + PC_VCTSXS = 0x122, + PC_VCTUXS = 0x123, + PC_VEXPTEFP = 0x124, + PC_VLOGEFP = 0x125, + PC_VMAXFP = 0x126, + PC_VMAXSB = 0x127, + PC_VMAXSH = 0x128, + PC_VMAXSW = 0x129, + PC_VMAXUB = 0x12A, + PC_VMAXUH = 0x12B, + PC_VMAXUW = 0x12C, + PC_VMINFP = 0x12D, + PC_VMINSB = 0x12E, + PC_VMINSH = 0x12F, + PC_VMINSW = 0x130, + PC_VMINUB = 0x131, + PC_VMINUH = 0x132, + PC_VMINUW = 0x133, + PC_VMRGHB = 0x134, + PC_VMRGHH = 0x135, + PC_VMRGHW = 0x136, + PC_VMRGLB = 0x137, + PC_VMRGLH = 0x138, + PC_VMRGLW = 0x139, + PC_VMULESB = 0x13A, + PC_VMULESH = 0x13B, + PC_VMULEUB = 0x13C, + PC_VMULEUH = 0x13D, + PC_VMULOSB = 0x13E, + PC_VMULOSH = 0x13F, + PC_VMULOUB = 0x140, + PC_VMULOUH = 0x141, + PC_VNOR = 0x142, + PC_VOR = 0x143, + PC_VPKPX = 0x144, + PC_VPKSHSS = 0x145, + PC_VPKSHUS = 0x146, + PC_VPKSWSS = 0x147, + PC_VPKSWUS = 0x148, + PC_VPKUHUM = 0x149, + PC_VPKUHUS = 0x14A, + PC_VPKUWUM = 0x14B, + PC_VPKUWUS = 0x14C, + PC_VREFP = 0x14D, + PC_VRFIM = 0x14E, + PC_VRFIN = 0x14F, + PC_VRFIP = 0x150, + PC_VRFIZ = 0x151, + PC_VRLB = 0x152, + PC_VRLH = 0x153, + PC_VRLW = 0x154, + PC_VRSQRTEFP = 0x155, + PC_VSL = 0x156, + PC_VSLB = 0x157, + PC_VSLH = 0x158, + PC_VSLO = 0x159, + PC_VSLW = 0x15A, + PC_VSPLTB = 0x15B, + PC_VSPLTH = 0x15C, + PC_VSPLTW = 0x15D, + PC_VSPLTISB = 0x15E, + PC_VSPLTISH = 0x15F, + PC_VSPLTISW = 0x160, + PC_VSR = 0x161, + PC_VSRAB = 0x162, + PC_VSRAH = 0x163, + PC_VSRAW = 0x164, + PC_VSRB = 0x165, + PC_VSRH = 0x166, + PC_VSRO = 0x167, + PC_VSRW = 0x168, + PC_VSUBCUW = 0x169, + PC_VSUBFP = 0x16A, + PC_VSUBSBS = 0x16B, + PC_VSUBSHS = 0x16C, + PC_VSUBSWS = 0x16D, + PC_VSUBUBM = 0x16E, + PC_VSUBUBS = 0x16F, + PC_VSUBUHM = 0x170, + PC_VSUBUHS = 0x171, + PC_VSUBUWM = 0x172, + PC_VSUBUWS = 0x173, + PC_VSUMSWS = 0x174, + PC_VSUM2SWS = 0x175, + PC_VSUM4SBS = 0x176, + PC_VSUM4SHS = 0x177, + PC_VSUM4UBS = 0x178, + PC_VUPKHPX = 0x179, + PC_VUPKHSB = 0x17A, + PC_VUPKHSH = 0x17B, + PC_VUPKLPX = 0x17C, + PC_VUPKLSB = 0x17D, + PC_VUPKLSH = 0x17E, + PC_VXOR = 0x17F, + PC_VMADDFP = 0x180, + PC_VMHADDSHS = 0x181, + PC_VMHRADDSHS = 0x182, + PC_VMLADDUHM = 0x183, + PC_VMSUMMBM = 0x184, + PC_VMSUMSHM = 0x185, + PC_VMSUMSHS = 0x186, + PC_VMSUMUBM = 0x187, + PC_VMSUMUHM = 0x188, + PC_VMSUMUHS = 0x189, + PC_VNMSUBFP = 0x18A, + PC_VPERM = 0x18B, + PC_VSEL = 0x18C, + PC_VSLDOI = 0x18D, + PC_VMR = 0x18E, + PC_VMRP = 0x18F, + PC_SLE = 0x190, + PC_SLEQ = 0x191, + PC_SLIQ = 0x192, + PC_SLLIQ = 0x193, + PC_SLLQ = 0x194, + PC_SLQ = 0x195, + PC_SRAIQ = 0x196, + PC_SRAQ = 0x197, + PC_SRE = 0x198, + PC_SREA = 0x199, + PC_SREQ = 0x19A, + PC_SRIQ = 0x19B, + PC_SRLIQ = 0x19C, + PC_SRLQ = 0x19D, + PC_SRQ = 0x19E, + PC_MASKG = 0x19F, + PC_MASKIR = 0x1A0, + PC_LSCBX = 0x1A1, + PC_DIV = 0x1A2, + PC_DIVS = 0x1A3, + PC_DOZ = 0x1A4, + PC_MUL = 0x1A5, + PC_NABS = 0x1A6, + PC_ABS = 0x1A7, + PC_CLCS = 0x1A8, + PC_DOZI = 0x1A9, + PC_RLMI = 0x1AA, + PC_RRIB = 0x1AB, + PC_PENTRY = 0x1AC, + PC_PEXIT = 0x1AD, + OPCODE_MAX = 0x1AE +};*/ +//#define PC_B 0x0 +//#define PC_BL 0x1 +//#define PC_BC 0x2 +//#define PC_BCLR 0x3 +//#define PC_BCCTR 0x4 +//#define PC_BT 0x5 +//#define PC_BTLR 0x6 +//#define PC_BTCTR 0x7 +//#define PC_BF 0x8 +//#define PC_BFLR 0x9 +//#define PC_BFCTR 0xA +//#define PC_BDNZ 0xB +//#define PC_BDNZT 0xC +//#define PC_BDNZF 0xD +//#define PC_BDZ 0xE +//#define PC_BDZT 0xF +//#define PC_BDZF 0x10 +//#define PC_BLR 0x11 +//#define PC_BCTR 0x12 +//#define PC_BCTRL 0x13 +//#define PC_BLRL 0x14 +//#define PC_LBZ 0x15 +//#define PC_LBZU 0x16 +//#define PC_LBZX 0x17 +//#define PC_LBZUX 0x18 +//#define PC_LHZ 0x19 +//#define PC_LHZU 0x1A +//#define PC_LHZX 0x1B +//#define PC_LHZUX 0x1C +//#define PC_LHA 0x1D +//#define PC_LHAU 0x1E +//#define PC_LHAX 0x1F +//#define PC_LHAUX 0x20 +//#define PC_LHBRX 0x21 +//#define PC_LWZ 0x22 +//#define PC_LWZU 0x23 +//#define PC_LWZX 0x24 +//#define PC_LWZUX 0x25 +//#define PC_LWBRX 0x26 +//#define PC_LMW 0x27 +//#define PC_STB 0x28 +//#define PC_STBU 0x29 +//#define PC_STBX 0x2A +//#define PC_STBUX 0x2B +//#define PC_STH 0x2C +//#define PC_STHU 0x2D +//#define PC_STHX 0x2E +//#define PC_STHUX 0x2F +//#define PC_STHBRX 0x30 +//#define PC_STW 0x31 +//#define PC_STWU 0x32 +//#define PC_STWX 0x33 +//#define PC_STWUX 0x34 +//#define PC_STWBRX 0x35 +//#define PC_STMW 0x36 +//#define PC_DCBF 0x37 +//#define PC_DCBST 0x38 +//#define PC_DCBT 0x39 +//#define PC_DCBTST 0x3A +//#define PC_DCBZ 0x3B +//#define PC_ADD 0x3C +//#define PC_ADDC 0x3D +//#define PC_ADDE 0x3E +//#define PC_ADDI 0x3F +//#define PC_ADDIC 0x40 +//#define PC_ADDICR 0x41 +//#define PC_ADDIS 0x42 +//#define PC_ADDME 0x43 +//#define PC_ADDZE 0x44 +//#define PC_DIVW 0x45 +//#define PC_DIVWU 0x46 +//#define PC_MULHW 0x47 +//#define PC_MULHWU 0x48 +//#define PC_MULLI 0x49 +//#define PC_MULLW 0x4A +//#define PC_NEG 0x4B +//#define PC_SUBF 0x4C +//#define PC_SUBFC 0x4D +//#define PC_SUBFE 0x4E +//#define PC_SUBFIC 0x4F +//#define PC_SUBFME 0x50 +//#define PC_SUBFZE 0x51 +//#define PC_CMPI 0x52 +//#define PC_CMP 0x53 +//#define PC_CMPLI 0x54 +//#define PC_CMPL 0x55 +//#define PC_ANDI 0x56 +//#define PC_ANDIS 0x57 +//#define PC_ORI 0x58 +//#define PC_ORIS 0x59 +//#define PC_XORI 0x5A +//#define PC_XORIS 0x5B +//#define PC_AND 0x5C +//#define PC_OR 0x5D +//#define PC_XOR 0x5E +//#define PC_NAND 0x5F +//#define PC_NOR 0x60 +//#define PC_EQV 0x61 +//#define PC_ANDC 0x62 +//#define PC_ORC 0x63 +//#define PC_EXTSB 0x64 +//#define PC_EXTSH 0x65 +//#define PC_CNTLZW 0x66 +//#define PC_RLWINM 0x67 +//#define PC_RLWNM 0x68 +//#define PC_RLWIMI 0x69 +//#define PC_SLW 0x6A +//#define PC_SRW 0x6B +//#define PC_SRAWI 0x6C +//#define PC_SRAW 0x6D +//#define PC_CRAND 0x6E +//#define PC_CRANDC 0x6F +//#define PC_CREQV 0x70 +//#define PC_CRNAND 0x71 +//#define PC_CRNOR 0x72 +//#define PC_CROR 0x73 +//#define PC_CRORC 0x74 +//#define PC_CRXOR 0x75 +//#define PC_MCRF 0x76 +//#define PC_MTXER 0x77 +//#define PC_MTCTR 0x78 +//#define PC_MTLR 0x79 +//#define PC_MTCRF 0x7A +//#define PC_MTMSR 0x7B +//#define PC_MTSPR 0x7C +//#define PC_MFMSR 0x7D +//#define PC_MFSPR 0x7E +//#define PC_MFXER 0x7F +//#define PC_MFCTR 0x80 +//#define PC_MFLR 0x81 +//#define PC_MFCR 0x82 +//#define PC_MFFS 0x83 +//#define PC_MTFSF 0x84 +//#define PC_EIEIO 0x85 +//#define PC_ISYNC 0x86 +//#define PC_SYNC 0x87 +//#define PC_RFI 0x88 +//#define PC_LI 0x89 +//#define PC_LIS 0x8A +//#define PC_MR 0x8B +//#define PC_NOP 0x8C +//#define PC_NOT 0x8D +//#define PC_LFS 0x8E +//#define PC_LFSU 0x8F +//#define PC_LFSX 0x90 +//#define PC_LFSUX 0x91 +//#define PC_LFD 0x92 +//#define PC_LFDU 0x93 +//#define PC_LFDX 0x94 +//#define PC_LFDUX 0x95 +//#define PC_STFS 0x96 +//#define PC_STFSU 0x97 +//#define PC_STFSX 0x98 +//#define PC_STFSUX 0x99 +//#define PC_STFD 0x9A +//#define PC_STFDU 0x9B +//#define PC_STFDX 0x9C +//#define PC_STFDUX 0x9D +//#define PC_FMR 0x9E +//#define PC_FABS 0x9F +//#define PC_FNEG 0xA0 +//#define PC_FNABS 0xA1 +//#define PC_FADD 0xA2 +//#define PC_FADDS 0xA3 +//#define PC_FSUB 0xA4 +//#define PC_FSUBS 0xA5 +//#define PC_FMUL 0xA6 +//#define PC_FMULS 0xA7 +//#define PC_FDIV 0xA8 +//#define PC_FDIVS 0xA9 +//#define PC_FMADD 0xAA +//#define PC_FMADDS 0xAB +//#define PC_FMSUB 0xAC +//#define PC_FMSUBS 0xAD +//#define PC_FNMADD 0xAE +//#define PC_FNMADDS 0xAF +//#define PC_FNMSUB 0xB0 +//#define PC_FNMSUBS 0xB1 +//#define PC_FRES 0xB2 +//#define PC_FRSQRTE 0xB3 +//#define PC_FSEL 0xB4 +//#define PC_FRSP 0xB5 +//#define PC_FCTIW 0xB6 +//#define PC_FCTIWZ 0xB7 +//#define PC_FCMPU 0xB8 +//#define PC_FCMPO 0xB9 +//#define PC_LWARX 0xBA +//#define PC_LSWI 0xBB +//#define PC_LSWX 0xBC +//#define PC_STFIWX 0xBD +//#define PC_STSWI 0xBE +//#define PC_STSWX 0xBF +//#define PC_STWCX 0xC0 +//#define PC_ECIWX 0xC1 +//#define PC_ECOWX 0xC2 +//#define PC_DCBI 0xC3 +//#define PC_ICBI 0xC4 +//#define PC_MCRFS 0xC5 +//#define PC_MCRXR 0xC6 +//#define PC_MFTB 0xC7 +//#define PC_MFSR 0xC8 +//#define PC_MTSR 0xC9 +//#define PC_MFSRIN 0xCA +//#define PC_MTSRIN 0xCB +//#define PC_MTFSB0 0xCC +//#define PC_MTFSB1 0xCD +//#define PC_MTFSFI 0xCE +//#define PC_SC 0xCF +//#define PC_FSQRT 0xD0 +//#define PC_FSQRTS 0xD1 +//#define PC_TLBIA 0xD2 +//#define PC_TLBIE 0xD3 +//#define PC_TLBLD 0xD4 +//#define PC_TLBLI 0xD5 +//#define PC_TLBSYNC 0xD6 +//#define PC_TW 0xD7 +//#define PC_TRAP 0xD8 +//#define PC_TWI 0xD9 +//#define PC_OPWORD 0xDA +//#define PC_MFROM 0xDB +//#define PC_DSA 0xDC +//#define PC_ESA 0xDD +//#define PC_DCCCI 0xDE +//#define PC_DCREAD 0xDF +//#define PC_ICBT 0xE0 +//#define PC_ICCCI 0xE1 +//#define PC_ICREAD 0xE2 +//#define PC_RFCI 0xE3 +//#define PC_TLBRE 0xE4 +//#define PC_TLBSX 0xE5 +//#define PC_TLBWE 0xE6 +//#define PC_WRTEE 0xE7 +//#define PC_WRTEEI 0xE8 +//#define PC_MFDCR 0xE9 +//#define PC_MTDCR 0xEA +//#define PC_DCBA 0xEB +//#define PC_DSS 0xEC +//#define PC_DSSALL 0xED +//#define PC_DST 0xEE +//#define PC_DSTT 0xEF +//#define PC_DSTST 0xF0 +//#define PC_DSTSTT 0xF1 +//#define PC_LVEBX 0xF2 +//#define PC_LVEHX 0xF3 +//#define PC_LVEWX 0xF4 +//#define PC_LVSL 0xF5 +//#define PC_LVSR 0xF6 +//#define PC_LVX 0xF7 +//#define PC_LVXL 0xF8 +//#define PC_STVEBX 0xF9 +//#define PC_STVEHX 0xFA +//#define PC_STVEWX 0xFB +//#define PC_STVX 0xFC +//#define PC_STVXL 0xFD +//#define PC_MFVSCR 0xFE +//#define PC_MTVSCR 0xFF +//#define PC_VADDCUW 0x100 +//#define PC_VADDFP 0x101 +//#define PC_VADDSBS 0x102 +//#define PC_VADDSHS 0x103 +//#define PC_VADDSWS 0x104 +//#define PC_VADDUBM 0x105 +//#define PC_VADDUBS 0x106 +//#define PC_VADDUHM 0x107 +//#define PC_VADDUHS 0x108 +//#define PC_VADDUWM 0x109 +//#define PC_VADDUWS 0x10A +//#define PC_VAND 0x10B +//#define PC_VANDC 0x10C +//#define PC_VAVGSB 0x10D +//#define PC_VAVGSH 0x10E +//#define PC_VAVGSW 0x10F +//#define PC_VAVGUB 0x110 +//#define PC_VAVGUH 0x111 +//#define PC_VAVGUW 0x112 +//#define PC_VCFSX 0x113 +//#define PC_VCFUX 0x114 +//#define PC_VCMPBFP 0x115 +//#define PC_VCMPEQFP 0x116 +//#define PC_VCMPEQUB 0x117 +//#define PC_VCMPEQUH 0x118 +//#define PC_VCMPEQUW 0x119 +//#define PC_VCMPGEFP 0x11A +//#define PC_VCMPGTFP 0x11B +//#define PC_VCMPGTSB 0x11C +//#define PC_VCMPGTSH 0x11D +//#define PC_VCMPGTSW 0x11E +//#define PC_VCMPGTUB 0x11F +//#define PC_VCMPGTUH 0x120 +//#define PC_VCMPGTUW 0x121 +//#define PC_VCTSXS 0x122 +//#define PC_VCTUXS 0x123 +//#define PC_VEXPTEFP 0x124 +//#define PC_VLOGEFP 0x125 +//#define PC_VMAXFP 0x126 +//#define PC_VMAXSB 0x127 +//#define PC_VMAXSH 0x128 +//#define PC_VMAXSW 0x129 +//#define PC_VMAXUB 0x12A +//#define PC_VMAXUH 0x12B +//#define PC_VMAXUW 0x12C +//#define PC_VMINFP 0x12D +//#define PC_VMINSB 0x12E +//#define PC_VMINSH 0x12F +//#define PC_VMINSW 0x130 +//#define PC_VMINUB 0x131 +//#define PC_VMINUH 0x132 +//#define PC_VMINUW 0x133 +//#define PC_VMRGHB 0x134 +//#define PC_VMRGHH 0x135 +//#define PC_VMRGHW 0x136 +//#define PC_VMRGLB 0x137 +//#define PC_VMRGLH 0x138 +//#define PC_VMRGLW 0x139 +//#define PC_VMULESB 0x13A +//#define PC_VMULESH 0x13B +//#define PC_VMULEUB 0x13C +//#define PC_VMULEUH 0x13D +//#define PC_VMULOSB 0x13E +//#define PC_VMULOSH 0x13F +//#define PC_VMULOUB 0x140 +//#define PC_VMULOUH 0x141 +//#define PC_VNOR 0x142 +//#define PC_VOR 0x143 +//#define PC_VPKPX 0x144 +//#define PC_VPKSHSS 0x145 +//#define PC_VPKSHUS 0x146 +//#define PC_VPKSWSS 0x147 +//#define PC_VPKSWUS 0x148 +//#define PC_VPKUHUM 0x149 +//#define PC_VPKUHUS 0x14A +//#define PC_VPKUWUM 0x14B +//#define PC_VPKUWUS 0x14C +//#define PC_VREFP 0x14D +//#define PC_VRFIM 0x14E +//#define PC_VRFIN 0x14F +//#define PC_VRFIP 0x150 +//#define PC_VRFIZ 0x151 +//#define PC_VRLB 0x152 +//#define PC_VRLH 0x153 +//#define PC_VRLW 0x154 +//#define PC_VRSQRTEFP 0x155 +//#define PC_VSL 0x156 +//#define PC_VSLB 0x157 +//#define PC_VSLH 0x158 +//#define PC_VSLO 0x159 +//#define PC_VSLW 0x15A +//#define PC_VSPLTB 0x15B +//#define PC_VSPLTH 0x15C +//#define PC_VSPLTW 0x15D +//#define PC_VSPLTISB 0x15E +//#define PC_VSPLTISH 0x15F +//#define PC_VSPLTISW 0x160 +//#define PC_VSR 0x161 +//#define PC_VSRAB 0x162 +//#define PC_VSRAH 0x163 +//#define PC_VSRAW 0x164 +//#define PC_VSRB 0x165 +//#define PC_VSRH 0x166 +//#define PC_VSRO 0x167 +//#define PC_VSRW 0x168 +//#define PC_VSUBCUW 0x169 +//#define PC_VSUBFP 0x16A +//#define PC_VSUBSBS 0x16B +//#define PC_VSUBSHS 0x16C +//#define PC_VSUBSWS 0x16D +//#define PC_VSUBUBM 0x16E +//#define PC_VSUBUBS 0x16F +//#define PC_VSUBUHM 0x170 +//#define PC_VSUBUHS 0x171 +//#define PC_VSUBUWM 0x172 +//#define PC_VSUBUWS 0x173 +//#define PC_VSUMSWS 0x174 +//#define PC_VSUM2SWS 0x175 +//#define PC_VSUM4SBS 0x176 +//#define PC_VSUM4SHS 0x177 +//#define PC_VSUM4UBS 0x178 +//#define PC_VUPKHPX 0x179 +//#define PC_VUPKHSB 0x17A +//#define PC_VUPKHSH 0x17B +//#define PC_VUPKLPX 0x17C +//#define PC_VUPKLSB 0x17D +//#define PC_VUPKLSH 0x17E +//#define PC_VXOR 0x17F +//#define PC_VMADDFP 0x180 +//#define PC_VMHADDSHS 0x181 +//#define PC_VMHRADDSHS 0x182 +//#define PC_VMLADDUHM 0x183 +//#define PC_VMSUMMBM 0x184 +//#define PC_VMSUMSHM 0x185 +//#define PC_VMSUMSHS 0x186 +//#define PC_VMSUMUBM 0x187 +//#define PC_VMSUMUHM 0x188 +//#define PC_VMSUMUHS 0x189 +//#define PC_VNMSUBFP 0x18A +//#define PC_VPERM 0x18B +//#define PC_VSEL 0x18C +//#define PC_VSLDOI 0x18D +//#define PC_VMR 0x18E +//#define PC_VMRP 0x18F +//#define PC_SLE 0x190 +//#define PC_SLEQ 0x191 +//#define PC_SLIQ 0x192 +//#define PC_SLLIQ 0x193 +//#define PC_SLLQ 0x194 +//#define PC_SLQ 0x195 +//#define PC_SRAIQ 0x196 +//#define PC_SRAQ 0x197 +//#define PC_SRE 0x198 +//#define PC_SREA 0x199 +//#define PC_SREQ 0x19A +//#define PC_SRIQ 0x19B +//#define PC_SRLIQ 0x19C +//#define PC_SRLQ 0x19D +//#define PC_SRQ 0x19E +//#define PC_MASKG 0x19F +//#define PC_MASKIR 0x1A0 +//#define PC_LSCBX 0x1A1 +//#define PC_DIV 0x1A2 +//#define PC_DIVS 0x1A3 +//#define PC_DOZ 0x1A4 +//#define PC_MUL 0x1A5 +//#define PC_NABS 0x1A6 +//#define PC_ABS 0x1A7 +//#define PC_CLCS 0x1A8 +//#define PC_DOZI 0x1A9 +//#define PC_RLMI 0x1AA +//#define PC_RRIB 0x1AB +//#define PC_PENTRY 0x1AC +//#define PC_PEXIT 0x1AD +//#define OPCODE_MAX 0x1AE +const short PC_B = 0x0; +const short PC_BL = 0x1; +const short PC_BC = 0x2; +const short PC_BCLR = 0x3; +const short PC_BCCTR = 0x4; +const short PC_BT = 0x5; +const short PC_BTLR = 0x6; +const short PC_BTCTR = 0x7; +const short PC_BF = 0x8; +const short PC_BFLR = 0x9; +const short PC_BFCTR = 0xA; +const short PC_BDNZ = 0xB; +const short PC_BDNZT = 0xC; +const short PC_BDNZF = 0xD; +const short PC_BDZ = 0xE; +const short PC_BDZT = 0xF; +const short PC_BDZF = 0x10; +const short PC_BLR = 0x11; +const short PC_BCTR = 0x12; +const short PC_BCTRL = 0x13; +const short PC_BLRL = 0x14; +const short PC_LBZ = 0x15; +const short PC_LBZU = 0x16; +const short PC_LBZX = 0x17; +const short PC_LBZUX = 0x18; +const short PC_LHZ = 0x19; +const short PC_LHZU = 0x1A; +const short PC_LHZX = 0x1B; +const short PC_LHZUX = 0x1C; +const short PC_LHA = 0x1D; +const short PC_LHAU = 0x1E; +const short PC_LHAX = 0x1F; +const short PC_LHAUX = 0x20; +const short PC_LHBRX = 0x21; +const short PC_LWZ = 0x22; +const short PC_LWZU = 0x23; +const short PC_LWZX = 0x24; +const short PC_LWZUX = 0x25; +const short PC_LWBRX = 0x26; +const short PC_LMW = 0x27; +const short PC_STB = 0x28; +const short PC_STBU = 0x29; +const short PC_STBX = 0x2A; +const short PC_STBUX = 0x2B; +const short PC_STH = 0x2C; +const short PC_STHU = 0x2D; +const short PC_STHX = 0x2E; +const short PC_STHUX = 0x2F; +const short PC_STHBRX = 0x30; +const short PC_STW = 0x31; +const short PC_STWU = 0x32; +const short PC_STWX = 0x33; +const short PC_STWUX = 0x34; +const short PC_STWBRX = 0x35; +const short PC_STMW = 0x36; +const short PC_DCBF = 0x37; +const short PC_DCBST = 0x38; +const short PC_DCBT = 0x39; +const short PC_DCBTST = 0x3A; +const short PC_DCBZ = 0x3B; +const short PC_ADD = 0x3C; +const short PC_ADDC = 0x3D; +const short PC_ADDE = 0x3E; +const short PC_ADDI = 0x3F; +const short PC_ADDIC = 0x40; +const short PC_ADDICR = 0x41; +const short PC_ADDIS = 0x42; +const short PC_ADDME = 0x43; +const short PC_ADDZE = 0x44; +const short PC_DIVW = 0x45; +const short PC_DIVWU = 0x46; +const short PC_MULHW = 0x47; +const short PC_MULHWU = 0x48; +const short PC_MULLI = 0x49; +const short PC_MULLW = 0x4A; +const short PC_NEG = 0x4B; +const short PC_SUBF = 0x4C; +const short PC_SUBFC = 0x4D; +const short PC_SUBFE = 0x4E; +const short PC_SUBFIC = 0x4F; +const short PC_SUBFME = 0x50; +const short PC_SUBFZE = 0x51; +const short PC_CMPI = 0x52; +const short PC_CMP = 0x53; +const short PC_CMPLI = 0x54; +const short PC_CMPL = 0x55; +const short PC_ANDI = 0x56; +const short PC_ANDIS = 0x57; +const short PC_ORI = 0x58; +const short PC_ORIS = 0x59; +const short PC_XORI = 0x5A; +const short PC_XORIS = 0x5B; +const short PC_AND = 0x5C; +const short PC_OR = 0x5D; +const short PC_XOR = 0x5E; +const short PC_NAND = 0x5F; +const short PC_NOR = 0x60; +const short PC_EQV = 0x61; +const short PC_ANDC = 0x62; +const short PC_ORC = 0x63; +const short PC_EXTSB = 0x64; +const short PC_EXTSH = 0x65; +const short PC_CNTLZW = 0x66; +const short PC_RLWINM = 0x67; +const short PC_RLWNM = 0x68; +const short PC_RLWIMI = 0x69; +const short PC_SLW = 0x6A; +const short PC_SRW = 0x6B; +const short PC_SRAWI = 0x6C; +const short PC_SRAW = 0x6D; +const short PC_CRAND = 0x6E; +const short PC_CRANDC = 0x6F; +const short PC_CREQV = 0x70; +const short PC_CRNAND = 0x71; +const short PC_CRNOR = 0x72; +const short PC_CROR = 0x73; +const short PC_CRORC = 0x74; +const short PC_CRXOR = 0x75; +const short PC_MCRF = 0x76; +const short PC_MTXER = 0x77; +const short PC_MTCTR = 0x78; +const short PC_MTLR = 0x79; +const short PC_MTCRF = 0x7A; +const short PC_MTMSR = 0x7B; +const short PC_MTSPR = 0x7C; +const short PC_MFMSR = 0x7D; +const short PC_MFSPR = 0x7E; +const short PC_MFXER = 0x7F; +const short PC_MFCTR = 0x80; +const short PC_MFLR = 0x81; +const short PC_MFCR = 0x82; +const short PC_MFFS = 0x83; +const short PC_MTFSF = 0x84; +const short PC_EIEIO = 0x85; +const short PC_ISYNC = 0x86; +const short PC_SYNC = 0x87; +const short PC_RFI = 0x88; +const short PC_LI = 0x89; +const short PC_LIS = 0x8A; +const short PC_MR = 0x8B; +const short PC_NOP = 0x8C; +const short PC_NOT = 0x8D; +const short PC_LFS = 0x8E; +const short PC_LFSU = 0x8F; +const short PC_LFSX = 0x90; +const short PC_LFSUX = 0x91; +const short PC_LFD = 0x92; +const short PC_LFDU = 0x93; +const short PC_LFDX = 0x94; +const short PC_LFDUX = 0x95; +const short PC_STFS = 0x96; +const short PC_STFSU = 0x97; +const short PC_STFSX = 0x98; +const short PC_STFSUX = 0x99; +const short PC_STFD = 0x9A; +const short PC_STFDU = 0x9B; +const short PC_STFDX = 0x9C; +const short PC_STFDUX = 0x9D; +const short PC_FMR = 0x9E; +const short PC_FABS = 0x9F; +const short PC_FNEG = 0xA0; +const short PC_FNABS = 0xA1; +const short PC_FADD = 0xA2; +const short PC_FADDS = 0xA3; +const short PC_FSUB = 0xA4; +const short PC_FSUBS = 0xA5; +const short PC_FMUL = 0xA6; +const short PC_FMULS = 0xA7; +const short PC_FDIV = 0xA8; +const short PC_FDIVS = 0xA9; +const short PC_FMADD = 0xAA; +const short PC_FMADDS = 0xAB; +const short PC_FMSUB = 0xAC; +const short PC_FMSUBS = 0xAD; +const short PC_FNMADD = 0xAE; +const short PC_FNMADDS = 0xAF; +const short PC_FNMSUB = 0xB0; +const short PC_FNMSUBS = 0xB1; +const short PC_FRES = 0xB2; +const short PC_FRSQRTE = 0xB3; +const short PC_FSEL = 0xB4; +const short PC_FRSP = 0xB5; +const short PC_FCTIW = 0xB6; +const short PC_FCTIWZ = 0xB7; +const short PC_FCMPU = 0xB8; +const short PC_FCMPO = 0xB9; +const short PC_LWARX = 0xBA; +const short PC_LSWI = 0xBB; +const short PC_LSWX = 0xBC; +const short PC_STFIWX = 0xBD; +const short PC_STSWI = 0xBE; +const short PC_STSWX = 0xBF; +const short PC_STWCX = 0xC0; +const short PC_ECIWX = 0xC1; +const short PC_ECOWX = 0xC2; +const short PC_DCBI = 0xC3; +const short PC_ICBI = 0xC4; +const short PC_MCRFS = 0xC5; +const short PC_MCRXR = 0xC6; +const short PC_MFTB = 0xC7; +const short PC_MFSR = 0xC8; +const short PC_MTSR = 0xC9; +const short PC_MFSRIN = 0xCA; +const short PC_MTSRIN = 0xCB; +const short PC_MTFSB0 = 0xCC; +const short PC_MTFSB1 = 0xCD; +const short PC_MTFSFI = 0xCE; +const short PC_SC = 0xCF; +const short PC_FSQRT = 0xD0; +const short PC_FSQRTS = 0xD1; +const short PC_TLBIA = 0xD2; +const short PC_TLBIE = 0xD3; +const short PC_TLBLD = 0xD4; +const short PC_TLBLI = 0xD5; +const short PC_TLBSYNC = 0xD6; +const short PC_TW = 0xD7; +const short PC_TRAP = 0xD8; +const short PC_TWI = 0xD9; +const short PC_OPWORD = 0xDA; +const short PC_MFROM = 0xDB; +const short PC_DSA = 0xDC; +const short PC_ESA = 0xDD; +const short PC_DCCCI = 0xDE; +const short PC_DCREAD = 0xDF; +const short PC_ICBT = 0xE0; +const short PC_ICCCI = 0xE1; +const short PC_ICREAD = 0xE2; +const short PC_RFCI = 0xE3; +const short PC_TLBRE = 0xE4; +const short PC_TLBSX = 0xE5; +const short PC_TLBWE = 0xE6; +const short PC_WRTEE = 0xE7; +const short PC_WRTEEI = 0xE8; +const short PC_MFDCR = 0xE9; +const short PC_MTDCR = 0xEA; +const short PC_DCBA = 0xEB; +const short PC_DSS = 0xEC; +const short PC_DSSALL = 0xED; +const short PC_DST = 0xEE; +const short PC_DSTT = 0xEF; +const short PC_DSTST = 0xF0; +const short PC_DSTSTT = 0xF1; +const short PC_LVEBX = 0xF2; +const short PC_LVEHX = 0xF3; +const short PC_LVEWX = 0xF4; +const short PC_LVSL = 0xF5; +const short PC_LVSR = 0xF6; +const short PC_LVX = 0xF7; +const short PC_LVXL = 0xF8; +const short PC_STVEBX = 0xF9; +const short PC_STVEHX = 0xFA; +const short PC_STVEWX = 0xFB; +const short PC_STVX = 0xFC; +const short PC_STVXL = 0xFD; +const short PC_MFVSCR = 0xFE; +const short PC_MTVSCR = 0xFF; +const short PC_VADDCUW = 0x100; +const short PC_VADDFP = 0x101; +const short PC_VADDSBS = 0x102; +const short PC_VADDSHS = 0x103; +const short PC_VADDSWS = 0x104; +const short PC_VADDUBM = 0x105; +const short PC_VADDUBS = 0x106; +const short PC_VADDUHM = 0x107; +const short PC_VADDUHS = 0x108; +const short PC_VADDUWM = 0x109; +const short PC_VADDUWS = 0x10A; +const short PC_VAND = 0x10B; +const short PC_VANDC = 0x10C; +const short PC_VAVGSB = 0x10D; +const short PC_VAVGSH = 0x10E; +const short PC_VAVGSW = 0x10F; +const short PC_VAVGUB = 0x110; +const short PC_VAVGUH = 0x111; +const short PC_VAVGUW = 0x112; +const short PC_VCFSX = 0x113; +const short PC_VCFUX = 0x114; +const short PC_VCMPBFP = 0x115; +const short PC_VCMPEQFP = 0x116; +const short PC_VCMPEQUB = 0x117; +const short PC_VCMPEQUH = 0x118; +const short PC_VCMPEQUW = 0x119; +const short PC_VCMPGEFP = 0x11A; +const short PC_VCMPGTFP = 0x11B; +const short PC_VCMPGTSB = 0x11C; +const short PC_VCMPGTSH = 0x11D; +const short PC_VCMPGTSW = 0x11E; +const short PC_VCMPGTUB = 0x11F; +const short PC_VCMPGTUH = 0x120; +const short PC_VCMPGTUW = 0x121; +const short PC_VCTSXS = 0x122; +const short PC_VCTUXS = 0x123; +const short PC_VEXPTEFP = 0x124; +const short PC_VLOGEFP = 0x125; +const short PC_VMAXFP = 0x126; +const short PC_VMAXSB = 0x127; +const short PC_VMAXSH = 0x128; +const short PC_VMAXSW = 0x129; +const short PC_VMAXUB = 0x12A; +const short PC_VMAXUH = 0x12B; +const short PC_VMAXUW = 0x12C; +const short PC_VMINFP = 0x12D; +const short PC_VMINSB = 0x12E; +const short PC_VMINSH = 0x12F; +const short PC_VMINSW = 0x130; +const short PC_VMINUB = 0x131; +const short PC_VMINUH = 0x132; +const short PC_VMINUW = 0x133; +const short PC_VMRGHB = 0x134; +const short PC_VMRGHH = 0x135; +const short PC_VMRGHW = 0x136; +const short PC_VMRGLB = 0x137; +const short PC_VMRGLH = 0x138; +const short PC_VMRGLW = 0x139; +const short PC_VMULESB = 0x13A; +const short PC_VMULESH = 0x13B; +const short PC_VMULEUB = 0x13C; +const short PC_VMULEUH = 0x13D; +const short PC_VMULOSB = 0x13E; +const short PC_VMULOSH = 0x13F; +const short PC_VMULOUB = 0x140; +const short PC_VMULOUH = 0x141; +const short PC_VNOR = 0x142; +const short PC_VOR = 0x143; +const short PC_VPKPX = 0x144; +const short PC_VPKSHSS = 0x145; +const short PC_VPKSHUS = 0x146; +const short PC_VPKSWSS = 0x147; +const short PC_VPKSWUS = 0x148; +const short PC_VPKUHUM = 0x149; +const short PC_VPKUHUS = 0x14A; +const short PC_VPKUWUM = 0x14B; +const short PC_VPKUWUS = 0x14C; +const short PC_VREFP = 0x14D; +const short PC_VRFIM = 0x14E; +const short PC_VRFIN = 0x14F; +const short PC_VRFIP = 0x150; +const short PC_VRFIZ = 0x151; +const short PC_VRLB = 0x152; +const short PC_VRLH = 0x153; +const short PC_VRLW = 0x154; +const short PC_VRSQRTEFP = 0x155; +const short PC_VSL = 0x156; +const short PC_VSLB = 0x157; +const short PC_VSLH = 0x158; +const short PC_VSLO = 0x159; +const short PC_VSLW = 0x15A; +const short PC_VSPLTB = 0x15B; +const short PC_VSPLTH = 0x15C; +const short PC_VSPLTW = 0x15D; +const short PC_VSPLTISB = 0x15E; +const short PC_VSPLTISH = 0x15F; +const short PC_VSPLTISW = 0x160; +const short PC_VSR = 0x161; +const short PC_VSRAB = 0x162; +const short PC_VSRAH = 0x163; +const short PC_VSRAW = 0x164; +const short PC_VSRB = 0x165; +const short PC_VSRH = 0x166; +const short PC_VSRO = 0x167; +const short PC_VSRW = 0x168; +const short PC_VSUBCUW = 0x169; +const short PC_VSUBFP = 0x16A; +const short PC_VSUBSBS = 0x16B; +const short PC_VSUBSHS = 0x16C; +const short PC_VSUBSWS = 0x16D; +const short PC_VSUBUBM = 0x16E; +const short PC_VSUBUBS = 0x16F; +const short PC_VSUBUHM = 0x170; +const short PC_VSUBUHS = 0x171; +const short PC_VSUBUWM = 0x172; +const short PC_VSUBUWS = 0x173; +const short PC_VSUMSWS = 0x174; +const short PC_VSUM2SWS = 0x175; +const short PC_VSUM4SBS = 0x176; +const short PC_VSUM4SHS = 0x177; +const short PC_VSUM4UBS = 0x178; +const short PC_VUPKHPX = 0x179; +const short PC_VUPKHSB = 0x17A; +const short PC_VUPKHSH = 0x17B; +const short PC_VUPKLPX = 0x17C; +const short PC_VUPKLSB = 0x17D; +const short PC_VUPKLSH = 0x17E; +const short PC_VXOR = 0x17F; +const short PC_VMADDFP = 0x180; +const short PC_VMHADDSHS = 0x181; +const short PC_VMHRADDSHS = 0x182; +const short PC_VMLADDUHM = 0x183; +const short PC_VMSUMMBM = 0x184; +const short PC_VMSUMSHM = 0x185; +const short PC_VMSUMSHS = 0x186; +const short PC_VMSUMUBM = 0x187; +const short PC_VMSUMUHM = 0x188; +const short PC_VMSUMUHS = 0x189; +const short PC_VNMSUBFP = 0x18A; +const short PC_VPERM = 0x18B; +const short PC_VSEL = 0x18C; +const short PC_VSLDOI = 0x18D; +const short PC_VMR = 0x18E; +const short PC_VMRP = 0x18F; +const short PC_SLE = 0x190; +const short PC_SLEQ = 0x191; +const short PC_SLIQ = 0x192; +const short PC_SLLIQ = 0x193; +const short PC_SLLQ = 0x194; +const short PC_SLQ = 0x195; +const short PC_SRAIQ = 0x196; +const short PC_SRAQ = 0x197; +const short PC_SRE = 0x198; +const short PC_SREA = 0x199; +const short PC_SREQ = 0x19A; +const short PC_SRIQ = 0x19B; +const short PC_SRLIQ = 0x19C; +const short PC_SRLQ = 0x19D; +const short PC_SRQ = 0x19E; +const short PC_MASKG = 0x19F; +const short PC_MASKIR = 0x1A0; +const short PC_LSCBX = 0x1A1; +const short PC_DIV = 0x1A2; +const short PC_DIVS = 0x1A3; +const short PC_DOZ = 0x1A4; +const short PC_MUL = 0x1A5; +const short PC_NABS = 0x1A6; +const short PC_ABS = 0x1A7; +const short PC_CLCS = 0x1A8; +const short PC_DOZI = 0x1A9; +const short PC_RLMI = 0x1AA; +const short PC_RRIB = 0x1AB; +const short PC_PENTRY = 0x1AC; +const short PC_PEXIT = 0x1AD; +const short OPCODE_MAX = 0x1AE; + +extern OpcodeInfo opcodeinfo[OPCODE_MAX]; + +extern void pcode_get_hi_lo(int bits, char typechar, SInt32 *hi, SInt32 *lo); +extern int pcode_check_imm_bits(SInt32 value, int bits, char typechar); +extern int pcode_const_from_format(const char *format, int *pResult); +extern PCode *vformatpcode(short opcode, va_list argList); +extern int expectandformatoperand(PCodeArg *operand, PCOpKind expectedKind, char a3, int bitCount, char *buf); +extern int formatoperand(PCodeArg *operand, char *buf); +extern void formatoperands(PCode *pcode, char *buf, int showBasicBlocks); +extern PCode *makecopyinstruction(PCodeArg *a, PCodeArg *b); +extern int is_location_independent(PCode *pcode); +extern int can_reuse_stored_value(PCode *a, PCode *b); +extern int nbytes_loaded_or_stored_by(PCode *pcode); +extern void change_num_operands(PCode *pcode, int newNum); +extern void change_opcode(PCode *pcode, short opcode); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/PCodeUtilities.h b/includes/compiler/PCodeUtilities.h new file mode 100644 index 0000000..312dd55 --- /dev/null +++ b/includes/compiler/PCodeUtilities.h @@ -0,0 +1,23 @@ +#ifndef COMPILER_PCODEUTILITIES_H +#define COMPILER_PCODEUTILITIES_H + +#include "compiler/common.h" + +extern void pcsetrecordbit(PCode *pc); +extern void pcsetsideeffects(PCode *pc); +extern void pcsetlinkbit(PCode *pc); +extern void branch_label(PCodeLabel *label); +extern void branch_conditional(short a, short compareop, short c, PCodeLabel *label); +extern void branch_always(PCodeLabel *label); +extern void branch_decrement_always(short opcode, PCodeLabel *label); +extern void branch_indirect(Object *obj); +extern int branch_count_volatiles(void); +extern PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks); +extern void branch_subroutine(Object *obj, short add_nop, UInt32 *masks); +extern void branch_subroutine_ctr(UInt32 *masks); +extern void add_immediate(short dest_reg, short base_reg, Object *obj, short offset); +extern PCode *add_immediate_lo(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block); +extern PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block); +extern void load_store_register(short opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset); + +#endif diff --git a/includes/compiler/StackFrame.h b/includes/compiler/StackFrame.h new file mode 100644 index 0000000..3145bdb --- /dev/null +++ b/includes/compiler/StackFrame.h @@ -0,0 +1,60 @@ +#ifndef COMPILER_STACKFRAME_H +#define COMPILER_STACKFRAME_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +enum ObjClass { + ObjClass0, + ObjClass1, + ObjClass2, + ObjClassMax +}; + +extern Boolean requires_frame; +extern Boolean makes_call; +extern Boolean uses_globals; +extern Boolean dynamic_stack; +extern Boolean large_stack; +extern Object *dummyvaparam; +extern void *dummyprofiler; + +extern void init_stack_globals(void); +extern void init_frame_sizes(void); +extern void assign_local_memory(Object *obj); +extern void assign_locals_to_memory(ObjectList *first); +extern void compute_frame_sizes(void); +extern void generate_prologue(PCodeBlock *block); +extern void generate_epilogue(PCodeBlock *block, Boolean add_blr); +extern void allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size); +extern char *generate_traceback(SInt32 funcsize, char *funcname, SInt32 *tbsize, Object *func); +extern void check_dynamic_aligned_frame(void); +extern void move_varargs_to_memory(void); +extern void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVarargs); +extern SInt32 set_out_param_displ(SInt32 a, Type *type, Boolean flag, SInt32 *outvar, SInt32 b); +extern SInt32 out_param_displ_to_offset(SInt32 displ); +extern Boolean needs_frame(void); +extern void update_out_param_size(SInt32 size); +extern void estimate_out_param_size(SInt32 size); +extern void update_out_param_align(SInt32 align); +extern void update_in_param_align(SInt32 align); +extern void update_frame_align(SInt32 align); +extern SInt32 local_offset_32(Object *obj); +extern SInt16 local_offset_lo(Object *obj, SInt32 offset); +extern SInt16 local_offset_ha(Object *obj, SInt32 offset); +extern SInt16 local_offset_16(Object *obj); +extern Boolean local_is_16bit_offset(Object *obj); +extern int local_base_register(Object *obj); +extern Boolean is_large_frame(void); +extern void no_frame_for_asm(void); +extern Boolean can_add_displ_to_local(Object *obj, SInt32 displ); +extern SInt32 get_alloca_alignment(void); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/TOC.h b/includes/compiler/TOC.h new file mode 100644 index 0000000..59ec8a1 --- /dev/null +++ b/includes/compiler/TOC.h @@ -0,0 +1,60 @@ +#ifndef COMPILER_TOC_H +#define COMPILER_TOC_H + +#include "compiler/common.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct CodeLabelList { + struct CodeLabelList *next; + Object *object; + CLabel *label; +} CodeLabelList; + +extern ObjectList *toclist; +extern ObjectList *exceptionlist; +extern void *descriptorlist; +extern void *floatconstpool; +extern void *doubleconstpool; +extern ObjectList *floatconstlist; +extern void *vectorconstpool; +extern ObjectList *vectorconstlist; +extern Object toc0; +extern Boolean no_descriptors; +extern Object pic_base; +extern VarInfo pic_base_varinfo; +extern short pic_base_reg; +extern CodeLabelList *codelabellist; + +extern void setupaddressing(void); +extern void createNonLazyPointer(Object *obj); +extern void referenceIndirectPointer(Object *obj); +extern Object *createIndirect(Object *obj, Boolean flag1, Boolean flag2); +extern Object *createfloatconstant(Type *type, Float *data); +extern Object *createvectorconstant(Type *type, MWVector128 *data); +extern void DeclarePooledConstants(); +extern Object *CreateFloatConst(Type *type, Float *data, SInt32 *unkptr); +extern void dumpcodelabels(Object *func); +typedef struct COVCResult { + // this struct might be used in other places too??? + short op1; + short op2; + unsigned char arg; +} COVCResult; +extern Boolean canoptimizevectorconst(MWVector128 *vecp, Type *type, COVCResult *result); +extern Boolean TOC_use_fsel(ENode *expr); +extern Boolean TOC_use_isel(ENode *expr, Boolean flag); +extern SInt32 GetSizeSkip(ENode *expr); +extern void Optimize64bitMath(ENode *expr); +extern void expandTOCreferences(Statement **stmts); +extern void resetTOCvarinfo(void); +extern Boolean needdescriptor(void); +extern Object *createstaticinitobject(void); + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +#endif diff --git a/includes/compiler/common.h b/includes/compiler/common.h index b5909e2..15043f5 100644 --- a/includes/compiler/common.h +++ b/includes/compiler/common.h @@ -94,27 +94,34 @@ typedef enum Section { SECT_MW_SWITCH = 30, SECT_8BYTE_LITERALS = 31, SECT_4BYTE_LITERALS = 32, + // one of these next 2 is missing in pro7 SECT_MOD_INIT_FUNC = 33, SECT_MOD_TERM_FUNC = 34, - SECT_CONST = 35, - SECT_CONST_PTR = 36, - SECT_NONLAZY_PTRS = 37, - SECT_COMMON_VARS = 38, - SECT_16BYTE_LITERALS = 39, - SECT_TEXT_COALESCE = 40, - SECT_DATA_COALESCE = 41, - SECT_UDATA_COALESCE = 42, - SECT_CONST_COALESCE = 43, - SECT_CONST_PTR_COALESCE = 44, - SECT_CSTR_COALESCE = 45, - N_SECTIONS = 46 + SECT_CONST = 34, + SECT_CONST_PTR = 35, + // everything after here is known ok + SECT_NONLAZY_PTRS = 36, + SECT_COMMON_VARS = 37, + SECT_16BYTE_LITERALS = 38, + SECT_TEXT_COALESCE = 39, + SECT_DATA_COALESCE = 40, + SECT_UDATA_COALESCE = 41, + SECT_CONST_COALESCE = 42, + SECT_CONST_PTR_COALESCE = 43, + SECT_CSTR_COALESCE = 44, + N_SECTIONS = 45 } Section; typedef struct BClassList BClassList; typedef struct CI_FuncData CI_FuncData; typedef struct CLabel CLabel; +typedef struct ClassList ClassList; +typedef struct CParams CParams; +typedef struct DeclInfo DeclInfo; +typedef struct DeclThing DeclThing; // rename me please typedef struct DefArgCtorInfo DefArgCtorInfo; typedef struct DepName DepName; +typedef struct EMemberInfo EMemberInfo; typedef struct ENode ENode; typedef struct ENodeList ENodeList; typedef struct ExceptionAction ExceptionAction; @@ -139,6 +146,11 @@ typedef struct Object Object; typedef struct ObjectList ObjectList; typedef struct ObjCInfo ObjCInfo; typedef struct ObjCMethod ObjCMethod; +typedef struct Operand Operand; +typedef struct PackedDeclInfo PackedDeclInfo; +typedef struct PCode PCode; +typedef struct PCodeArg PCodeArg; +typedef struct PCodeBlock PCodeBlock; typedef struct PCodeLabel PCodeLabel; typedef struct PointsToFunction PointsToFunction; typedef struct PTFList PTFList; @@ -166,6 +178,7 @@ typedef struct TypeClass TypeClass; typedef struct TypeEnum TypeEnum; typedef struct TypeFunc TypeFunc; typedef struct TypeIntegral TypeIntegral; +typedef struct TypeList TypeList; typedef struct TypeMemberPointer TypeMemberPointer; typedef struct TypeMethod TypeMethod; typedef struct TypePointer TypePointer; @@ -173,6 +186,7 @@ typedef struct TypeStruct TypeStruct; typedef struct TypeTemplDep TypeTemplDep; typedef struct VarInfo VarInfo; typedef struct VarRecord VarRecord; +typedef struct VClassList VClassList; // Common bits for templates typedef enum TemplParamType { @@ -262,7 +276,12 @@ enum { Q_BYCOPY = 0x2000, Q_BYREF = 0x4000, Q_ONEWAY = 0x8000, + Q_10000 = 0x10000, + Q_20000 = 0x20000, + Q_OVERLOAD = 0x40000, // weak + Q_80000 = 0x80000, Q_RESTRICT = 0x200000, + Q_1000000 = 0x1000000, Q_ALIGNED_1 = 0x2000000, Q_ALIGNED_2 = 0x4000000, Q_ALIGNED_4 = 0x6000000, @@ -280,4 +299,42 @@ enum { Q_ALIGNED_MASK = 0x1E000000 }; +enum { + EXPORT_FLAGS_INTERNAL = 0x10, + EXPORT_FLAGS_IMPORT = 0x20, + EXPORT_FLAGS_EXPORT = 0x40 +}; + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct CParams { + CWPluginContext context; + CWObjectData objectdata; + Handle objectDataHandle; + Handle browseDataHandle; + SInt32 pluginRequest; + SInt32 apiVersion; + FSSpec projectFile; + SInt32 projectFileCount; + SInt32 mainFileNumber; + FSSpec mainFileSpec; + const char *mainFileText; + SInt32 mainFileTextLength; + Boolean isPrecompiling; + Boolean isAutoPrecompiling; + Boolean isPreprocessing; + Boolean isGeneratingDebugInfo; + Boolean isCachingPrecompiledHeaders; + CWBrowseOptions browseOptions; + Boolean field276; + SInt16 mainFileID; + CWDataType targetOS; + CWDataType targetCPU; + char *targetName; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + #endif diff --git a/includes/compiler/enode.h b/includes/compiler/enode.h index 6e0ab2c..e12b1ae 100644 --- a/includes/compiler/enode.h +++ b/includes/compiler/enode.h @@ -75,6 +75,7 @@ typedef enum ENodeType { ESETCONST, ENEWEXCEPTION, ENEWEXCEPTIONARRAY, + EMYSTERY67, // no name??? EOBJLIST, EMEMBER, ETEMPLDEP, @@ -88,6 +89,15 @@ typedef enum ENodeType { } ENodeType; +struct EMemberInfo { + BClassList *path; + ENodeList *nodes; + void *x8; + void *xC; + void *x10; +}; + + struct ENodeList { ENodeList *next; ENode *node; @@ -116,7 +126,7 @@ typedef union ENodeUnion { ENodeList *args; TypeFunc *functype; } funccall; - ObjAccess objaccess; + //ObjAccess objaccess; struct { ENode *accessnode; ENode *mfpointer; @@ -135,7 +145,7 @@ typedef union ENodeUnion { struct { SInt32 size; char *data; - SInt32 segnum; + //SInt32 segnum; ?? char ispascal; char ispacked; } string; @@ -159,6 +169,10 @@ typedef union ENodeUnion { Object *objref; SInt32 offset; } addr; + struct { + NameSpaceObjectList *list; + TemplArg *templargs; + } objlist; void *inst; MemInitializer *ctorinit; Statement *stmt; @@ -187,7 +201,7 @@ typedef union ENodeUnion { HashNameNode *name; TemplArg *args; } qualtempl; - ObjAccess objaccess; + //ObjAccess objaccess; struct { ENode *expr; TStreamElement *token; @@ -197,7 +211,8 @@ typedef union ENodeUnion { ENode *expr; ENodeList *args; } funccall; - struct { + // have my doubts about this one + /*struct { Type *type; UInt32 qual; ENode *arraydim; @@ -205,7 +220,7 @@ typedef union ENodeUnion { ENodeList *initlist; Boolean is_global; Boolean has_init; - } nw; + } nw;*/ struct { ENode *expr; Boolean is_global; @@ -242,7 +257,7 @@ typedef union ENodeUnion { struct ENode { ENodeType type; UInt8 cost; - UInt16 flags; // &1, &2 correspond to quals + UInt16 flags; Boolean ignored; Boolean hascall; // void *loc; - might not be in pro7? @@ -254,9 +269,16 @@ struct ENode { enum { ENODE_FLAG_CONST = Q_CONST, ENODE_FLAG_VOLATILE = Q_VOLATILE, - ENODE_FLAG_QUALS = Q_CONST | Q_VOLATILE + ENODE_FLAG_QUALS = Q_CONST | Q_VOLATILE, + ENODE_FLAG_10 = 0x10, + ENODE_FLAG_80 = 0x80 }; +#define ENODE_IS(_enode, _etype) ( (_enode)->type == (_etype) ) +#define ENODE_IS2(_enode, _etype1, _etype2) ( ENODE_IS(_enode, (_etype1)) || ENODE_IS(_enode, (_etype2)) ) +#define ENODE_IS3(_enode, _etype1, _etype2, _etype3) ( ENODE_IS(_enode, (_etype1)) || ENODE_IS(_enode, (_etype2)) || ENODE_IS(_enode, (_etype3)) ) +#define ENODE_IS_RANGE(_enode, _lo, _hi) ( ((_enode)->type >= (_lo)) && ((_enode)->type <= (_hi)) ) + #ifdef __MWERKS__ #pragma options align=reset #endif diff --git a/includes/compiler/objects.h b/includes/compiler/objects.h index 32552ec..5f01d26 100644 --- a/includes/compiler/objects.h +++ b/includes/compiler/objects.h @@ -47,7 +47,7 @@ struct ObjType { ObjectType otype; AccessType access; Type *type; - void *unk6; + UInt32 qual; }; @@ -184,6 +184,25 @@ struct Object { } u; }; +enum { + OBJECT_FLAGS_UNUSED = 1, + OBJECT_FLAGS_2 = 2, + OBJECT_FLAGS_4 = 4, + OBJECT_FLAGS_8 = 8, + OBJECT_FLAGS_10 = 0x10, // internal + OBJECT_FLAGS_20 = 0x20, // import + OBJECT_FLAGS_40 = 0x40, // export + OBJECT_FLAGS_60 = 0x60 // lib export +}; + +enum { + OBJECT_SCLASS_101 = 0x101, + OBJECT_SCLASS_102 = 0x102, + OBJECT_SCLASS_103 = 0x103, + OBJECT_SCLASS_104 = 0x104, + OBJECT_SCLASS_12B = 0x12B +}; + #define OBJ_BASE(obj) ((ObjBase *) (obj)) #define OBJ_ENUM_CONST(obj) ((ObjEnumConst *) (obj)) #define OBJ_TYPE(obj) ((ObjType *) (obj)) @@ -193,8 +212,30 @@ struct Object { #define OBJ_MEMBER_VAR_PATH(obj) ((ObjMemberVarPath *) (obj)) #define OBJECT(obj) ((Object *) (obj)) -#endif + +struct VarInfo { // OK! + Object *func; + SInt32 usage; + TStreamElement deftoken; + SInt16 varnumber; + Boolean noregister; + Boolean used; + UInt8 flags; + UInt8 rclass; + SInt16 reg; + SInt16 regHi; +}; + +enum { + VarInfoFlag1 = 1, // is parameter? + VarInfoFlag2 = 2, + VarInfoFlag4 = 4, + VarInfoFlag40 = 0x40, + VarInfoFlag80 = 0x80 +}; #ifdef __MWERKS__ #pragma options align=reset #endif + +#endif diff --git a/includes/compiler/templates.h b/includes/compiler/templates.h index f188e0d..85bc5ec 100644 --- a/includes/compiler/templates.h +++ b/includes/compiler/templates.h @@ -143,6 +143,10 @@ struct TemplClass { UInt8 flags; }; +enum { + TEMPLCLASS_FLAGS_2 = 2 +}; + struct TemplClassInst { TypeClass theclass; TemplClassInst *next; @@ -150,7 +154,8 @@ struct TemplClassInst { TemplClass *templ; TemplArg *inst_args; TemplArg *oargs; - void *x46; + Boolean x46; + Boolean x47; }; #define TEMPL_CLASS(ty) ( (TemplClass *) (ty) ) diff --git a/includes/compiler/tokens.h b/includes/compiler/tokens.h index b574a81..2f49f98 100644 --- a/includes/compiler/tokens.h +++ b/includes/compiler/tokens.h @@ -39,7 +39,15 @@ typedef enum EToken { TK_UNION, TK_ENUM, TK_CLASS, - TK_UU_VECTOR = 283, + TK_UNK_113, + TK_UNK_114, + TK_UNK_115, + TK_UNK_116, + TK_UNK_117, + TK_UNK_118, + TK_UNK_119, + TK_UNK_11A, + TK_UU_VECTOR, TK_UU_TYPEOF_UU, TK_BOOL, TK_WCHAR_T, @@ -138,7 +146,9 @@ typedef enum EToken { TK_AT_DEFS, TK_SELF, TK_SUPER, - TK_UU_ALIGNOF_UU = 388, + TK_NEW_ARRAY, + TK_DELETE_ARRAY, + TK_UU_ALIGNOF_UU, TK_RESTRICT, TK_UU_ATTRIBUTE_UU, TK_UU_UUIDOF @@ -146,7 +156,7 @@ typedef enum EToken { typedef struct FileOffsetInfo { CPrepFileInfo *file; - SInt32 offset; + SInt32 tokenline; SInt32 tokenoffset; Boolean is_inline; } FileOffsetInfo; diff --git a/includes/compiler/types.h b/includes/compiler/types.h index 9b07590..e5b4d94 100644 --- a/includes/compiler/types.h +++ b/includes/compiler/types.h @@ -90,6 +90,7 @@ struct StructMember { enum { STRUCT_TYPE_STRUCT = 0, STRUCT_TYPE_UNION = 1, + STRUCT_TYPE_CLASS = 2, STRUCT_TYPE_4 = 4, STRUCT_TYPE_5 = 5, STRUCT_TYPE_6 = 6, @@ -104,23 +105,23 @@ enum { }; -typedef struct ClassList { // checked via CPrec - struct ClassList *next; +struct ClassList { // checked via CPrec + ClassList *next; TypeClass *base; SInt32 offset; SInt32 voffset; AccessType access; Boolean is_virtual; -} ClassList; +}; -typedef struct VClassList { // checked via CPrec - struct VClassList *next; +struct VClassList { // checked via CPrec + VClassList *next; TypeClass *base; SInt32 offset; SInt32 voffset; Boolean has_override; char alignsave; -} VClassList; +}; typedef struct ClassFriend { // checked via CPrec struct ClassFriend *next; @@ -162,14 +163,42 @@ struct TypeClass { UInt8 eflags; }; +typedef enum { + CLASS_MODE_0 = 0, + CLASS_MODE_1 = 1, + CLASS_MODE_2 = 2 +} ClassMode; + enum { + CLASS_FLAGS_1 = 1, CLASS_FLAGS_2 = 2, + CLASS_FLAGS_ABSTRACT = 8, + CLASS_FLAGS_10 = 0x10, CLASS_FLAGS_20 = 0x20, + CLASS_FLAGS_40 = 0x40, + CLASS_FLAGS_80 = 0x80, CLASS_FLAGS_100 = 0x100, // is TemplClass CLASS_FLAGS_800 = 0x800, // is TemplClassInst - CLASS_FLAGS_900 = 0x900 + CLASS_FLAGS_900 = 0x900, + CLASS_FLAGS_1000 = 0x1000, + CLASS_FLAGS_2000 = 0x2000, + CLASS_FLAGS_4000 = 0x4000, + CLASS_FLAGS_8000 = 0x8000 }; +/// maps to TypeClass::eflags +enum { + CLASS_EFLAGS_INTERNAL = 1, + CLASS_EFLAGS_IMPORT = 2, + CLASS_EFLAGS_EXPORT = 4 +}; + +enum { + CLASS_ACTION_0 = 0, + CLASS_ACTION_1 = 1, + CLASS_ACTION_2 = 2, + CLASS_ACTION_3 = 3 // __javaobject +}; typedef struct ExceptSpecList { struct ExceptSpecList *next; @@ -199,14 +228,29 @@ struct TypeFunc { }; enum { FUNC_FLAGS_PASCAL = 1, // on TypeFunc::flags + FUNC_FLAGS_2 = 2, + FUNC_FLAGS_4 = 4, + FUNC_FLAGS_8 = 8, // abstract? FUNC_FLAGS_METHOD = 0x10, FUNC_FLAGS_40 = 0x40, // func that's like "operator SomeOtherType()" + FUNC_FLAGS_80 = 0x80, + FUNC_FLAGS_100 = 0x100, + FUNC_FLAGS_200 = 0x200, + FUNC_FLAGS_NOTHROW = 0x400, + FUNC_FLAGS_800 = 0x800, FUNC_FLAGS_1000 = 0x1000, FUNC_FLAGS_2000 = 0x2000, - FUNC_FLAGS_100000 = 0x100000, - FUNC_FLAGS_900000 = 0x900000 + FUNC_FLAGS_CONST = 0x8000, + FUNC_FLAGS_VOLATILE = 0x10000, + FUNC_FLAGS_100000 = 0x100000, // is template? + FUNC_FLAGS_800000 = 0x800000, + FUNC_FLAGS_900000 = 0x900000, + FUNC_FLAGS_4000000 = 0x4000000, + FUNC_FLAGS_10000000 = 0x10000000, + FUNC_FLAGS_F0000000 = 0xF0000000 }; +// This is actually called TypeMemberFunc... // There seems to be a version of this which adds a class pointer at the end struct TypeMethod { TypeType type; @@ -217,7 +261,7 @@ struct TypeMethod { UInt32 qual; UInt32 flags; TypeClass *theclass; - void *x1E; + SInt32 x1E; // vtable offset? void *x22; Boolean x26; }; @@ -227,7 +271,7 @@ struct TypeBitfield { TypeType type; SInt32 size; Type *bitfieldtype; - unsigned char unkA; + char unkA; char unkB; }; @@ -305,7 +349,14 @@ struct TypePointer { // ObjCID +struct TypeList { + TypeList *next; + Type *type; +}; + + // Not sure if these existed originally, but they'll help +#define TYPE(ty) ((Type *) (ty)) #define TYPE_INTEGRAL(ty) ((TypeIntegral *) (ty)) #define TYPE_ENUM(ty) ((TypeEnum *) (ty)) #define TYPE_STRUCT(ty) ((TypeStruct *) (ty)) @@ -317,6 +368,34 @@ struct TypePointer { #define TYPE_MEMBER_POINTER(ty) ((TypeMemberPointer *) (ty)) #define TYPE_POINTER(ty) ((TypePointer *) (ty)) +#define IS_TYPE_VOID(ty) ( (ty)->type == TYPEVOID ) +#define IS_TYPE_INT(ty) ( (ty)->type == TYPEINT ) +#define IS_TYPE_ENUM(ty) ( (ty)->type == TYPEENUM ) +#define IS_TYPE_INT_OR_ENUM(ty) ( IS_TYPE_INT(ty) || IS_TYPE_ENUM(ty) ) +#define IS_TYPE_FLOAT(ty) ( (ty)->type == TYPEFLOAT ) +#define IS_TYPE_STRUCT(ty) ( (ty)->type == TYPESTRUCT ) +#define IS_TYPE_CLASS(ty) ( (ty)->type == TYPECLASS ) +#define IS_TYPE_FUNC(ty) ( (ty)->type == TYPEFUNC ) +#define IS_TYPEFUNC_METHOD(ty) ( (ty)->flags & FUNC_FLAGS_METHOD ) +#define IS_TYPE_TEMPLATE(ty) ( (ty)->type == TYPETEMPLATE ) +#define IS_TYPE_POINTER(ty) ( (ty)->type == TYPEPOINTER || (ty)->type == TYPEARRAY ) +#define IS_TYPE_POINTER_ONLY(ty) ( (ty)->type == TYPEPOINTER ) +#define IS_TYPE_REFERENCE(ty) ( (ty)->type == TYPEPOINTER && (TYPE_POINTER(ty)->qual & Q_REFERENCE) ) +#define IS_TYPEPOINTER_REFERENCE(ty) ( (ty)->qual & Q_REFERENCE ) +#define IS_TYPE_ARRAY(ty) ( (ty)->type == TYPEARRAY ) +#define IS_TYPE_BITFIELD(ty) ( (ty)->type == TYPEBITFIELD ) +#define IS_TYPESTRUCT_VECTOR(ty) ( (ty)->stype >= STRUCT_TYPE_4 && (ty)->stype <= STRUCT_TYPE_E ) +#define IS_TYPE_VECTOR(ty) ( (ty)->type == TYPESTRUCT && IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(ty)) ) +#define IS_TYPE_NONVECTOR_STRUCT(ty) ( (ty)->type == TYPESTRUCT && !IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(ty)) ) +#define IS_TYPE_MEMBERPOINTER(ty) ( (ty)->type == TYPEMEMBERPOINTER ) +#define IS_TYPE_4BYTES_MEMBERPOINTER(ty) ( ((ty)->type == TYPEMEMBERPOINTER) && ((ty)->size == 4u) ) +#define IS_TYPE_12BYTES_MEMBERPOINTER(ty) ( ((ty)->type == TYPEMEMBERPOINTER) && ((ty)->size == 12u) ) +#define TYPE_FITS_IN_REGISTER(ty) ( ((ty)->type == TYPEINT) || ((ty)->type == TYPEENUM) || (IS_TYPE_POINTER(ty) && ((ty)->type != TYPEARRAY)) || IS_TYPE_4BYTES_MEMBERPOINTER(ty) ) +#define TYPE_IS_8BYTES(ty) ( (((ty)->type == TYPEINT) || ((ty)->type == TYPEENUM)) && ((ty)->size == 8) ) + +#define OBJ_GET_TARGET_VOLATILE(obj) ( IS_TYPE_POINTER((obj)->type) ? (TYPE_POINTER((obj)->type)->qual & Q_VOLATILE) : ((obj)->qual & Q_VOLATILE) ) +#define OBJ_GET_TARGET_CONST(obj) ( IS_TYPE_POINTER((obj)->type) ? (TYPE_POINTER((obj)->type)->qual & Q_CONST) : ((obj)->qual & Q_CONST) ) + #ifdef __MWERKS__ #pragma options align=reset #endif diff --git a/includes/cos.h b/includes/cos.h index 777b380..3cb9402 100644 --- a/includes/cos.h +++ b/includes/cos.h @@ -22,7 +22,7 @@ extern SInt32 COS_GetTicks(); extern SInt32 COS_GetTime(); extern void COS_GetString(char *buffer, SInt16 strListID, SInt16 index); extern void COS_GetPString(StringPtr buffer, SInt16 strListID, SInt16 index); -extern Boolean COS_IsMultiByte(const char *str, int offset); +extern Boolean COS_IsMultiByte(const char *str1, const char *str2); extern OSErr COS_FileNew(const FSSpec *spec, SInt16 *refNum, OSType creator, OSType fileType); extern OSErr COS_FileOpen(const FSSpec *spec, SInt16 *refNum); extern OSErr COS_FileGetType(const FSSpec *spec, OSType *fileType); diff --git a/includes/oslib.h b/includes/oslib.h index 9aedb8d..4de46e9 100644 --- a/includes/oslib.h +++ b/includes/oslib.h @@ -176,7 +176,7 @@ extern int OS_OpenLibrary(const char *a, void **lib); extern int OS_GetLibrarySymbol(void *a, void *b, void **sym); extern int OS_CloseLibrary(void *a); extern int OS_LoadMacResourceFork(const OSSpec *spec, void **file_data, SInt32 *file_len); -extern Boolean OS_IsMultiByte(const char *str, int offset); +extern Boolean OS_IsMultiByte(const char *str1, const char *str2); /********************************/ /* FileHandles */ @@ -57,30 +57,30 @@ DONE compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Plugin/libimp-ma ---- ?? TargetSetWarningFlags, TargetDisplayWarningOptions ---- WarningHelpers.c ----- CCompiler.c ----- CParser.c +DONE CCompiler.c +STUB CParser.c DONE compiler_and_linker/FrontEnd/Common/CompilerTools.c (except for endian work) ---- CodeGenOptPPC.c ---- IrOptimizer.c ----- CodeGen.c ----- CPrep.c ----- CScope.c ----- CMachine.c ----- CExpr.c ----- CFunc.c +PART CodeGen.c +MOST CPrep.c +MOST CScope.c +MOST CMachine.c +STUB CExpr.c +STUB CFunc.c ---- CTemplateNew.c STUB CError.c ---- ObjGenMachO.c ----- CDecl.c ----- CMangler.c +STUB CDecl.c +DONE CMangler.c ---- CSOM.c ----- CABI.c ----- CInit.c ----- CClass.c +STUB CABI.c +STUB CInit.c +STUB CClass.c ---- CIRTransform.c ---- CObjC.c ----- CInline.c ----- CPrepTokenizer.c +STUB CInline.c +PART CPrepTokenizer.c ---- CTemplateTools.c ---- IroPointerAnalysis.c ---- InstrSelection.c @@ -102,15 +102,15 @@ STUB CError.c ---- IroLoop.c ---- IroExprRegeneration.c ---- IroSubable.c ----- RegisterInfo.c ----- TOC.c ----- StackFrame.c ----- Register.sc -PART PCode.c +MOST RegisterInfo.c +MOST TOC.c +MOST StackFrame.c +MOST Registers.c +DONE PCode.c ---- Switch.c ---- ValueNumbering.c ----- PCodeUtilities.c ----- Operands.c +DONE PCodeUtilities.c +MOST Operands.c ---- Exceptions.c ---- ?? Dumping (DumpIR, DumpExpression, ...) ---- COptimizer.c @@ -122,9 +122,9 @@ PART PCode.c ---- PCodeAssembly.c ---- Intrinsics.c ---- PPCError.c ----- CExpr2.c +STUB CExpr2.c DONE* CInt64.c ----- CPrec.c +PART CPrec.c ---- CBrowse.c ---- CPreprocess.c ---- FuncLevelAsmPPC.c @@ -140,7 +140,7 @@ DONE* CInt64.c ---- GenStabs.c ---- CTemplateFunc.c ---- IroMalloc.c -STUB PCodeInfo.c +PART PCodeInfo.c ---- StructMoves.c ---- FunctionCalls.c ---- IroBitVect.c diff --git a/unsorted/uCOS.c b/unsorted/uCOS.c index 5564e5b..68f8832 100644 --- a/unsorted/uCOS.c +++ b/unsorted/uCOS.c @@ -140,8 +140,8 @@ void COS_GetPString(StringPtr buffer, SInt16 strListID, SInt16 index) { GetIndString((StringPtr) buffer, strListID, index); } -Boolean COS_IsMultiByte(const char *str, int offset) { - return OS_IsMultiByte(str, offset); +Boolean COS_IsMultiByte(const char *str1, const char *str2) { + return OS_IsMultiByte(str1, str2); } OSErr COS_FileNew(const FSSpec *spec, SInt16 *refNum, OSType creator, OSType fileType) { |