@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2014, Alexey Frunze
|
Copyright (c) 2012-2015, Alexey Frunze
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -637,14 +637,22 @@ void GenFxnProlog(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
void GenLocalAlloc(int size)
|
void GenGrowStack(int size)
|
||||||
{
|
{
|
||||||
|
if (!size)
|
||||||
|
return;
|
||||||
GenPrintInstr3Operands(MipsInstrSubU, 0,
|
GenPrintInstr3Operands(MipsInstrSubU, 0,
|
||||||
MipsOpRegSp, 0,
|
MipsOpRegSp, 0,
|
||||||
MipsOpRegSp, 0,
|
MipsOpRegSp, 0,
|
||||||
MipsOpConst, size);
|
MipsOpConst, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
void GenFxnProlog2(void)
|
||||||
|
{
|
||||||
|
GenGrowStack(-CurFxnMinLocalOfs);
|
||||||
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
void GenFxnEpilog(void)
|
void GenFxnEpilog(void)
|
||||||
{
|
{
|
||||||
@@ -669,6 +677,12 @@ void GenFxnEpilog(void)
|
|||||||
MipsOpRegRa, 0);
|
MipsOpRegRa, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
int GenMaxLocalsSize(void)
|
||||||
|
{
|
||||||
|
return 0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
int GenGetBinaryOperatorInstr(int tok)
|
int GenGetBinaryOperatorInstr(int tok)
|
||||||
{
|
{
|
||||||
@@ -1706,7 +1720,7 @@ void GenExpr0(void)
|
|||||||
GenPushReg();
|
GenPushReg();
|
||||||
gotUnary = 0;
|
gotUnary = 0;
|
||||||
if (maxCallDepth != 1 && v < 16)
|
if (maxCallDepth != 1 && v < 16)
|
||||||
GenLocalAlloc(16 - v);
|
GenGrowStack(16 - v);
|
||||||
paramOfs = v - 4;
|
paramOfs = v - 4;
|
||||||
if (maxCallDepth == 1 && paramOfs >= 0 && paramOfs <= 12)
|
if (maxCallDepth == 1 && paramOfs >= 0 && paramOfs <= 12)
|
||||||
{
|
{
|
||||||
@@ -1760,7 +1774,7 @@ void GenExpr0(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GenLocalAlloc(16);
|
GenGrowStack(16);
|
||||||
}
|
}
|
||||||
if (stack[i - 1][0] == tokIdent)
|
if (stack[i - 1][0] == tokIdent)
|
||||||
{
|
{
|
||||||
@@ -1774,7 +1788,7 @@ void GenExpr0(void)
|
|||||||
}
|
}
|
||||||
if (v < 16)
|
if (v < 16)
|
||||||
v = 16;
|
v = 16;
|
||||||
GenLocalAlloc(-v);
|
GenGrowStack(-v);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tokUnaryStar:
|
case tokUnaryStar:
|
||||||
@@ -2399,4 +2413,3 @@ void GenFin(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2014, Alexey Frunze
|
Copyright (c) 2012-2015, Alexey Frunze
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -827,8 +827,10 @@ void GenFxnProlog(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
void GenLocalAlloc(int size)
|
void GenGrowStack(int size)
|
||||||
{
|
{
|
||||||
|
if (!size)
|
||||||
|
return;
|
||||||
#ifdef CAN_COMPILE_32BIT
|
#ifdef CAN_COMPILE_32BIT
|
||||||
if (SizeOfWord == 4 &&
|
if (SizeOfWord == 4 &&
|
||||||
OutputFormat != FormatSegHuge &&
|
OutputFormat != FormatSegHuge &&
|
||||||
@@ -860,6 +862,12 @@ void GenLocalAlloc(int size)
|
|||||||
X86OpConst, size);
|
X86OpConst, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
void GenFxnProlog2(void)
|
||||||
|
{
|
||||||
|
GenGrowStack(-CurFxnMinLocalOfs);
|
||||||
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
void GenFxnEpilog(void)
|
void GenFxnEpilog(void)
|
||||||
{
|
{
|
||||||
@@ -867,6 +875,16 @@ void GenFxnEpilog(void)
|
|||||||
GenPrintInstrNoOperand(X86InstrRet);
|
GenPrintInstrNoOperand(X86InstrRet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
int GenMaxLocalsSize(void)
|
||||||
|
{
|
||||||
|
#ifdef CAN_COMPILE_32BIT
|
||||||
|
if (SizeOfWord == 4 && OutputFormat != FormatSegHuge)
|
||||||
|
return 0x7FFFFFFF;
|
||||||
|
#endif
|
||||||
|
return 0x7FFF;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CAN_COMPILE_32BIT
|
#ifdef CAN_COMPILE_32BIT
|
||||||
/*
|
/*
|
||||||
struct INTREGS
|
struct INTREGS
|
||||||
@@ -2654,8 +2672,7 @@ void GenExpr1(void)
|
|||||||
GenPrintInstr1Operand(X86InstrCall, 0,
|
GenPrintInstr1Operand(X86InstrCall, 0,
|
||||||
X86OpRegAWord, 0);
|
X86OpRegAWord, 0);
|
||||||
}
|
}
|
||||||
if (v)
|
GenGrowStack(-v);
|
||||||
GenLocalAlloc(-v);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '(':
|
case '(':
|
||||||
@@ -2759,8 +2776,7 @@ void GenExpr0(void)
|
|||||||
#endif
|
#endif
|
||||||
GenPrintInstr1Operand(X86InstrCall, 0,
|
GenPrintInstr1Operand(X86InstrCall, 0,
|
||||||
X86OpRegAWord, 0);
|
X86OpRegAWord, 0);
|
||||||
if (v)
|
GenGrowStack(-v);
|
||||||
GenLocalAlloc(-v);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tokUnaryStar:
|
case tokUnaryStar:
|
||||||
@@ -3318,6 +3334,109 @@ void GenFin(void)
|
|||||||
puts2(CodeFooter);
|
puts2(CodeFooter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
if (StructPushLabel)
|
||||||
|
{
|
||||||
|
char s[1 + 2 + (2 + CHAR_BIT * sizeof StructPushLabel) / 3];
|
||||||
|
char *p = s + sizeof s;
|
||||||
|
|
||||||
|
*--p = '\0';
|
||||||
|
p = lab2str(p, StructPushLabel);
|
||||||
|
*--p = '_';
|
||||||
|
*--p = '_';
|
||||||
|
|
||||||
|
if (OutputFormat != FormatFlat)
|
||||||
|
puts2(CodeHeader);
|
||||||
|
|
||||||
|
GenLabel(p, 1);
|
||||||
|
GenFxnProlog();
|
||||||
|
|
||||||
|
if (SizeOfWord == 2)
|
||||||
|
{
|
||||||
|
puts2("\tmov\tdx, [bp+2]\n" // dx = return address
|
||||||
|
"\tmov\tsi, [bp+4]\n" // si = &struct
|
||||||
|
"\tmov\tcx, [bp+6]\n" // cx = sizeof(struct)
|
||||||
|
"\tmov\tbp, [bp]\n" // restore bp
|
||||||
|
|
||||||
|
"\tmov\tax, cx\n" // ax = sizeof(struct)
|
||||||
|
"\tinc\tax\n" // ax = sizeof(struct) + 1
|
||||||
|
"\tand\tax, -2\n" // ax = sizeof(struct) rounded up to multiple of 2 bytes
|
||||||
|
"\tadd\tsp, 4*2\n" // remove bp, return address and 2 args from stack
|
||||||
|
"\tsub\tsp, ax"); // allocate stack space for struct
|
||||||
|
|
||||||
|
puts2("\tmov\tdi, sp\n" // di = where struct should be copied to
|
||||||
|
"\tcld\n"
|
||||||
|
"\trep\tmovsb\n" // copy
|
||||||
|
|
||||||
|
"\tpop\tax\n" // return first 2 bytes of struct in ax
|
||||||
|
"\tpush\tax\n"
|
||||||
|
"\tpush\tbyte 0\n" // caller will remove this 0 and first 2 bytes of struct from stack (as 2 args)
|
||||||
|
"\tpush\tdx\n" // and then it will push ax (first 2 bytes of struct) back
|
||||||
|
"\tret"); // actually return to return address saved in dx
|
||||||
|
}
|
||||||
|
#ifdef CAN_COMPILE_32BIT
|
||||||
|
else if (OutputFormat != FormatSegHuge)
|
||||||
|
{
|
||||||
|
// Copying the pushed structure to the stack backwards
|
||||||
|
// (from higher to lower addresses) in order to correctly
|
||||||
|
// grow the stack on Windows, page by page
|
||||||
|
puts2("\tmov\tedx, [ebp+4]\n" // edx = return address
|
||||||
|
"\tmov\tesi, [ebp+8]\n" // esi = &struct
|
||||||
|
"\tmov\tecx, [ebp+12]\n" // ecx = sizeof(struct)
|
||||||
|
"\tmov\tebp, [ebp]\n" // restore ebp
|
||||||
|
|
||||||
|
"\tlea\teax, [ecx + 3]\n" // eax = sizeof(struct) + 3
|
||||||
|
"\tand\teax, -4\n" // eax = sizeof(struct) rounded up to multiple of 4 bytes
|
||||||
|
"\tadd\tesp, 4*4\n" // remove ebp, return address and 2 args from stack
|
||||||
|
"\tsub\tesp, eax"); // allocate stack space for struct
|
||||||
|
|
||||||
|
puts2("\tlea\tesi, [esi + ecx - 1]\n" // esi = &last byte of struct
|
||||||
|
"\tlea\tedi, [esp + ecx - 1]\n" // edi = where it should be copied to
|
||||||
|
"\tstd\n"
|
||||||
|
"\trep\tmovsb\n" // copy
|
||||||
|
"\tcld\n"
|
||||||
|
|
||||||
|
"\tmov\teax, [esp]\n" // return first 4 bytes of struct in eax
|
||||||
|
"\tpush\t0\n" // caller will remove this 0 and first 4 bytes of struct from stack (as 2 args)
|
||||||
|
"\tpush\tedx\n" // and then it will push eax (first 4 bytes of struct) back
|
||||||
|
"\tret"); // actually return to return address saved in edx
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
puts2("\tmov\tedx, [ebp+4]\n" // edx = return address (seg:ofs)
|
||||||
|
"\tmov\tesi, [ebp+8]\n" // esi = &struct (phys)
|
||||||
|
"\tror\tesi, 4\n"
|
||||||
|
"\tmov\tds, si\n"
|
||||||
|
"\tshr\tesi, 28\n" // ds:si = &struct (seg:ofs)
|
||||||
|
"\tmov\tecx, [ebp+12]\n" // ecx = sizeof(struct)
|
||||||
|
"\tmov\tebp, [ebp]\n" // restore ebp
|
||||||
|
|
||||||
|
"\tlea\teax, [ecx + 3]\n" // eax = sizeof(struct) + 3
|
||||||
|
"\tand\teax, -4\n" // eax = sizeof(struct) rounded up to multiple of 4 bytes
|
||||||
|
"\tadd\tsp, 4*4\n" // remove ebp, return address and 2 args from stack
|
||||||
|
"\tsub\tsp, ax"); // allocate stack space for struct
|
||||||
|
|
||||||
|
puts2("\tmov\tax, ss\n"
|
||||||
|
"\tmov\tes, ax\n" // es = ss
|
||||||
|
"\tmov\tdi, sp\n" // es:di = where struct should be copied to (seg:ofs)
|
||||||
|
"\tcld\n"
|
||||||
|
"\trep\tmovsb\n" // copy; limit to ~64KB since stack size itself is ~64KB max
|
||||||
|
|
||||||
|
"\tpop\teax\n" // return first 4 bytes of struct in eax
|
||||||
|
"\tpush\teax\n"
|
||||||
|
"\tpush\teax\n" // caller will remove this and first 4 bytes of struct from stack (as 2 args)
|
||||||
|
"\tpush\tedx\n" // and then it will push eax (first 4 bytes of struct) back
|
||||||
|
"\tretf"); // actually return to return address saved in edx
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GenFxnEpilog();
|
||||||
|
|
||||||
|
if (OutputFormat != FormatFlat)
|
||||||
|
puts2(CodeFooter);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SWITCH_TAB
|
#ifdef USE_SWITCH_TAB
|
||||||
if (SwitchJmpLabel)
|
if (SwitchJmpLabel)
|
||||||
{
|
{
|
||||||
@@ -3477,4 +3596,3 @@ void GenFin(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2012-2014, Alexey Frunze
|
Copyright (c) 2012-2015, Alexey Frunze
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -35,6 +35,7 @@ either expressed or implied, of the FreeBSD Project.
|
|||||||
/* */
|
/* */
|
||||||
/* Produces 16/32-bit 80386 assembly output for NASM. */
|
/* Produces 16/32-bit 80386 assembly output for NASM. */
|
||||||
/* Produces 32-bit MIPS assembly output for gcc/as. */
|
/* Produces 32-bit MIPS assembly output for gcc/as. */
|
||||||
|
/* Produces 32-bit TR3200 assembly output for vasm. */
|
||||||
/* */
|
/* */
|
||||||
/* Main file */
|
/* Main file */
|
||||||
/* */
|
/* */
|
||||||
@@ -55,6 +56,20 @@ either expressed or implied, of the FreeBSD Project.
|
|||||||
#define NO_FUNC_
|
#define NO_FUNC_
|
||||||
#define NO_EXTRA_WARNS
|
#define NO_EXTRA_WARNS
|
||||||
#define NO_FOR_DECL
|
#define NO_FOR_DECL
|
||||||
|
#define NO_STRUCT_BY_VAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Passing and returning structures by value is currenly supported
|
||||||
|
// on x86 only
|
||||||
|
#ifdef MIPS
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
#define NO_STRUCT_BY_VAL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef TR3200
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
#define NO_STRUCT_BY_VAL
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __SMALLER_C__
|
#ifndef __SMALLER_C__
|
||||||
@@ -404,12 +419,14 @@ void GenJumpIfEqual(int val, int Label);
|
|||||||
STATIC
|
STATIC
|
||||||
void GenFxnProlog(void);
|
void GenFxnProlog(void);
|
||||||
STATIC
|
STATIC
|
||||||
|
void GenFxnProlog2(void);
|
||||||
|
STATIC
|
||||||
void GenFxnEpilog(void);
|
void GenFxnEpilog(void);
|
||||||
void GenIsrProlog(void);
|
void GenIsrProlog(void);
|
||||||
void GenIsrEpilog(void);
|
void GenIsrEpilog(void);
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
void GenLocalAlloc(int Size);
|
int GenMaxLocalsSize(void);
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
unsigned GenStrData(int generatingCode, unsigned requiredLen);
|
unsigned GenStrData(int generatingCode, unsigned requiredLen);
|
||||||
@@ -631,21 +648,20 @@ int SizeOfWord = 2; // in chars (char can be a multiple of octets); ints and poi
|
|||||||
// TBD??? implement a function to allocate N labels with overflow checks
|
// TBD??? implement a function to allocate N labels with overflow checks
|
||||||
int LabelCnt = 1; // label counter for jumps
|
int LabelCnt = 1; // label counter for jumps
|
||||||
int StructCpyLabel = 0; // label of the function to copy structures/unions
|
int StructCpyLabel = 0; // label of the function to copy structures/unions
|
||||||
|
int StructPushLabel = 0; // label of the function to push structures/unions onto the stack
|
||||||
|
|
||||||
// call stack (from higher to lower addresses):
|
// call stack (from higher to lower addresses):
|
||||||
// param n
|
// arg n
|
||||||
// ...
|
// ...
|
||||||
// param 1
|
// arg 1
|
||||||
// return address
|
// return address
|
||||||
// saved xbp register
|
// saved xbp register
|
||||||
// local var 1
|
// local var 1
|
||||||
// ...
|
// ...
|
||||||
// local var n
|
// local var n
|
||||||
int CurFxnSyntaxPtr = 0;
|
int CurFxnSyntaxPtr = 0;
|
||||||
int CurFxnParamCnt = 0;
|
|
||||||
int CurFxnParamCntMin = 0;
|
int CurFxnParamCntMin = 0;
|
||||||
int CurFxnParamCntMax = 0;
|
int CurFxnParamCntMax = 0;
|
||||||
int CurFxnParamOfs = 0; // positive
|
|
||||||
int CurFxnLocalOfs = 0; // negative
|
int CurFxnLocalOfs = 0; // negative
|
||||||
int CurFxnMinLocalOfs = 0; // negative
|
int CurFxnMinLocalOfs = 0; // negative
|
||||||
|
|
||||||
@@ -2173,7 +2189,11 @@ int GetToken(void)
|
|||||||
#endif
|
#endif
|
||||||
#include "cgmips.c"
|
#include "cgmips.c"
|
||||||
#else
|
#else
|
||||||
|
#ifdef TR3200
|
||||||
|
#include "cgtr3k2.c"
|
||||||
|
#else
|
||||||
#include "cgx86.c"
|
#include "cgx86.c"
|
||||||
|
#endif // #ifdef TR3200
|
||||||
#endif // #ifdef MIPS
|
#endif // #ifdef MIPS
|
||||||
|
|
||||||
// expr.c code
|
// expr.c code
|
||||||
@@ -3106,6 +3126,26 @@ void simplifyConstExpr(int val, int isConst, int* ExprTypeSynPtr, int top, int b
|
|||||||
del(bottom, top - bottom);
|
del(bottom, top - bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
int AllocLocal(unsigned size)
|
||||||
|
{
|
||||||
|
// Let's calculate variable's relative on-stack location
|
||||||
|
int oldOfs = CurFxnLocalOfs;
|
||||||
|
|
||||||
|
// Note: local vars are word-aligned on the stack
|
||||||
|
CurFxnLocalOfs = uint2int((CurFxnLocalOfs - size) & ~(SizeOfWord - 1u));
|
||||||
|
if (CurFxnLocalOfs >= oldOfs ||
|
||||||
|
CurFxnLocalOfs != truncInt(CurFxnLocalOfs) ||
|
||||||
|
CurFxnLocalOfs < -GenMaxLocalsSize())
|
||||||
|
//error("AllocLocal(): Local variables take too much space\n");
|
||||||
|
errorVarSize();
|
||||||
|
|
||||||
|
if (CurFxnMinLocalOfs > CurFxnLocalOfs)
|
||||||
|
CurFxnMinLocalOfs = CurFxnLocalOfs;
|
||||||
|
|
||||||
|
return CurFxnLocalOfs;
|
||||||
|
}
|
||||||
|
|
||||||
// DONE: sizeof(type)
|
// DONE: sizeof(type)
|
||||||
// DONE: "sizeof expr"
|
// DONE: "sizeof expr"
|
||||||
// DONE: constant expressions
|
// DONE: constant expressions
|
||||||
@@ -3253,7 +3293,7 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
#ifdef CAN_COMPILE_32BIT
|
#ifdef CAN_COMPILE_32BIT
|
||||||
if (castSize && castSize != SizeOfWord && -castSize != SizeOfWord)
|
if (castSize && castSize != SizeOfWord)
|
||||||
{
|
{
|
||||||
if (castSize == 2)
|
if (castSize == 2)
|
||||||
{
|
{
|
||||||
@@ -3269,7 +3309,7 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
s -= 0x10000;
|
s -= 0x10000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // fallthrough
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// cast to int/unsigned/pointer
|
// cast to int/unsigned/pointer
|
||||||
@@ -4006,45 +4046,142 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
int tmpSynPtr, c;
|
int tmpSynPtr, c;
|
||||||
int minParams, maxParams;
|
int minParams, maxParams;
|
||||||
int firstParamSynPtr;
|
int firstParamSynPtr;
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
int oldIdx, oldSp;
|
||||||
|
unsigned structSize = 0;
|
||||||
|
int retStruct = 0;
|
||||||
|
int retOfs = 0;
|
||||||
|
#endif
|
||||||
exprval(idx, ExprTypeSynPtr, ConstExpr);
|
exprval(idx, ExprTypeSynPtr, ConstExpr);
|
||||||
|
|
||||||
if (!GetFxnInfo(*ExprTypeSynPtr, &minParams, &maxParams, ExprTypeSynPtr, &firstParamSynPtr))
|
if (!GetFxnInfo(*ExprTypeSynPtr, &minParams, &maxParams, ExprTypeSynPtr, &firstParamSynPtr))
|
||||||
//error("exprval(): function or function pointer expected\n");
|
//error("exprval(): function or function pointer expected\n");
|
||||||
errorOpType();
|
errorOpType();
|
||||||
|
|
||||||
// DONE: validate the number of function parameters
|
// DONE: validate the number of function arguments
|
||||||
// DONE: warnings on int<->pointer substitution in params
|
// DONE: warnings on int<->pointer substitution in params/args
|
||||||
|
|
||||||
// evaluate function parameters
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
// If a structure is returned, allocate space for it on the stack
|
||||||
|
// and pass its location as the first (implicit) argument.
|
||||||
|
if (ParseLevel &&
|
||||||
|
*ExprTypeSynPtr >= 0 &&
|
||||||
|
SyntaxStack[*ExprTypeSynPtr][0] == tokStructPtr)
|
||||||
|
{
|
||||||
|
unsigned sz = GetDeclSize(*ExprTypeSynPtr, 0);
|
||||||
|
// Make sure the return structure type is complete
|
||||||
|
if (!sz)
|
||||||
|
errorOpType();
|
||||||
|
retOfs = AllocLocal(sz);
|
||||||
|
// Transform fxn(args) into fxn(pretval, args)
|
||||||
|
ins(*idx + 1, ',');
|
||||||
|
ins2(*idx + 1, tokLocalOfs, retOfs);
|
||||||
|
retStruct = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// evaluate function arguments
|
||||||
c = 0;
|
c = 0;
|
||||||
while (stack[*idx][0] != '(')
|
while (stack[*idx][0] != '(')
|
||||||
{
|
{
|
||||||
// add a comma after the first (last to be pushed) parameter,
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
// so all parameters can be pushed whenever a comma is encountered
|
int gotStructs;
|
||||||
|
#endif
|
||||||
|
// add a comma after the first (last to be pushed) argument,
|
||||||
|
// so all arguments can be pushed whenever a comma is encountered
|
||||||
if (!c)
|
if (!c)
|
||||||
ins(*idx + 1, ',');
|
ins(*idx + 1, ',');
|
||||||
|
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
oldIdx = *idx;
|
||||||
|
oldSp = sp;
|
||||||
|
#endif
|
||||||
exprval(idx, &tmpSynPtr, ConstExpr);
|
exprval(idx, &tmpSynPtr, ConstExpr);
|
||||||
//error("exprval(): function parameters cannot be of type 'void'\n");
|
//error("exprval(): function arguments cannot be of type 'void'\n");
|
||||||
|
|
||||||
|
#ifdef NO_STRUCT_BY_VAL
|
||||||
scalarTypeCheck(tmpSynPtr);
|
scalarTypeCheck(tmpSynPtr);
|
||||||
|
#else
|
||||||
|
nonVoidTypeCheck(tmpSynPtr);
|
||||||
|
|
||||||
|
// If the argument is a structure, push it by calling a dedicated function
|
||||||
|
gotStructs = tmpSynPtr >= 0 && SyntaxStack[tmpSynPtr][0] == tokStructPtr;
|
||||||
|
if (gotStructs)
|
||||||
|
{
|
||||||
|
unsigned sz = GetDeclSize(tmpSynPtr, 0);
|
||||||
|
int i = oldIdx - (oldSp - sp);
|
||||||
|
stack[i][0] = ')';
|
||||||
|
stack[i][1] = SizeOfWord * 2;
|
||||||
|
|
||||||
|
if (!StructPushLabel)
|
||||||
|
StructPushLabel = LabelCnt++;
|
||||||
|
|
||||||
|
// The code generator expects functions to return values.
|
||||||
|
// If a function argument is a value produced by another function,
|
||||||
|
// as is the case here, the code generator will naturally
|
||||||
|
// want/need to push something of the size of the machine word.
|
||||||
|
// This works perfectly with non-structures.
|
||||||
|
// But we only want to push the structure without pushing any other words.
|
||||||
|
// In order to avoid involving changes in the code generator,
|
||||||
|
// we make the function that pushes structures onto the stack
|
||||||
|
// push all words but the first one. The dedicated function will
|
||||||
|
// return this word and the code generator will push it.
|
||||||
|
// This is ugly.
|
||||||
|
|
||||||
|
ins2(i, tokIdent, AddNumericIdent__(StructPushLabel));
|
||||||
|
ins(i, ',');
|
||||||
|
i = *idx + 1;
|
||||||
|
ins(i, ',');
|
||||||
|
ins2(i, tokNumUint, uint2int(sz));
|
||||||
|
ins2(i, '(', SizeOfWord * 2);
|
||||||
|
|
||||||
|
if (sz > (unsigned)GenMaxLocalsSize())
|
||||||
|
errorVarSize();
|
||||||
|
// Structures will be padded to machine word boundary when pushed
|
||||||
|
sz = (sz + SizeOfWord - 1) & ~(SizeOfWord - 1u);
|
||||||
|
// Count the cumulative size of the pushed structures, excluding
|
||||||
|
// the first words that will be pushed by the code generator
|
||||||
|
if (structSize + sz < structSize)
|
||||||
|
errorVarSize();
|
||||||
|
structSize += sz - SizeOfWord;
|
||||||
|
if (structSize > (unsigned)GenMaxLocalsSize())
|
||||||
|
errorVarSize();
|
||||||
|
// TBD??? complete overflow checks (an expression may contain more than one call)?
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (++c > maxParams)
|
if (++c > maxParams)
|
||||||
error("Too many function parameters\n");
|
error("Too many function arguments\n");
|
||||||
|
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
#ifndef CHECK_FXN_ARGS
|
||||||
|
#define CHECK_FXN_ARGS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NO_EXTRA_WARNS
|
#ifndef NO_EXTRA_WARNS
|
||||||
// Issue a warning if the parameter has to be a pointer but isn't and vice versa.
|
#ifndef CHECK_FXN_ARGS
|
||||||
|
#define CHECK_FXN_ARGS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHECK_FXN_ARGS
|
||||||
|
// Issue a warning if the argument has to be a pointer but isn't and vice versa.
|
||||||
|
// DONE: struct type compat checks
|
||||||
// TBD??? Compare pointer types deeply as in compatCheck()???
|
// TBD??? Compare pointer types deeply as in compatCheck()???
|
||||||
// TBD??? Issue a similar warning for return values and initializers???
|
// TBD??? Issue a similar warning for return values and initializers???
|
||||||
if (c <= minParams)
|
if (c <= minParams)
|
||||||
{
|
{
|
||||||
|
int t;
|
||||||
|
#ifndef NO_EXTRA_WARNS
|
||||||
int gotPtr = tmpSynPtr < 0;
|
int gotPtr = tmpSynPtr < 0;
|
||||||
int needPtr;
|
int needPtr;
|
||||||
int t;
|
|
||||||
if (!gotPtr)
|
if (!gotPtr)
|
||||||
{
|
{
|
||||||
t = SyntaxStack[tmpSynPtr][0];
|
t = SyntaxStack[tmpSynPtr][0];
|
||||||
gotPtr = (t == '*') | (t == '[') | (t == '('); // arrays and functions decay to pointers
|
gotPtr = (t == '*') | (t == '[') | (t == '('); // arrays and functions decay to pointers
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// Find the type of the formal parameter in the function declaration
|
// Find the type of the formal parameter in the function declaration
|
||||||
while ((t = SyntaxStack[firstParamSynPtr][0]) != tokIdent)
|
while ((t = SyntaxStack[firstParamSynPtr][0]) != tokIdent)
|
||||||
{
|
{
|
||||||
@@ -4061,6 +4198,17 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
firstParamSynPtr++;
|
firstParamSynPtr++;
|
||||||
}
|
}
|
||||||
firstParamSynPtr++;
|
firstParamSynPtr++;
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
gotStructs += (SyntaxStack[firstParamSynPtr][0] == tokStructPtr) * 2;
|
||||||
|
if (gotStructs)
|
||||||
|
{
|
||||||
|
// Structures must be of the same type
|
||||||
|
if (gotStructs != 3 ||
|
||||||
|
SyntaxStack[tmpSynPtr][1] != SyntaxStack[firstParamSynPtr][1])
|
||||||
|
errorOpType();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef NO_EXTRA_WARNS
|
||||||
needPtr = SyntaxStack[firstParamSynPtr][0] == '*';
|
needPtr = SyntaxStack[firstParamSynPtr][0] == '*';
|
||||||
if (needPtr != gotPtr &&
|
if (needPtr != gotPtr &&
|
||||||
// Make an exception for integer constants equal to 0, treat them as NULL pointers
|
// Make an exception for integer constants equal to 0, treat them as NULL pointers
|
||||||
@@ -4070,9 +4218,10 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
!stack[*idx + 1][1]
|
!stack[*idx + 1][1]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
warning("Expected %spointer in parameter %d\n", needPtr ? "" : "non-", c);
|
warning("Expected %spointer in argument %d\n", needPtr ? "" : "non-", c);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif // NO_EXTRA_WARNS
|
#endif // CHECK_FXN_ARGS
|
||||||
|
|
||||||
if (stack[*idx][0] == ',')
|
if (stack[*idx][0] == ',')
|
||||||
--*idx;
|
--*idx;
|
||||||
@@ -4080,10 +4229,31 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
--*idx;
|
--*idx;
|
||||||
|
|
||||||
if (c < minParams)
|
if (c < minParams)
|
||||||
error("Too few function parameters\n");
|
error("Too few function arguments\n");
|
||||||
|
|
||||||
// store the cumulative parameter size in the function call operators
|
// store the cumulative argument size in the function call operators
|
||||||
stack[1 + *idx][1] = stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = c * SizeOfWord;
|
{
|
||||||
|
int i = oldIdxRight + 1 - (oldSpRight - sp);
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
// Count the implicit param/arg for returned structure
|
||||||
|
c += retStruct;
|
||||||
|
#endif
|
||||||
|
stack[1 + *idx][1] = stack[i][1] = c * SizeOfWord;
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
// Correct the value by which the stack pointer
|
||||||
|
// will be incremented after the call
|
||||||
|
stack[i][1] += structSize;
|
||||||
|
// If a structure is returned, transform
|
||||||
|
// fxn(pretval, args) into *(fxn(pretval, args), pretval)
|
||||||
|
if (retStruct)
|
||||||
|
{
|
||||||
|
ins(i + 1, tokUnaryStar);
|
||||||
|
ins(i + 1, tokComma);
|
||||||
|
ins2(i + 1, tokLocalOfs, retOfs);
|
||||||
|
ins(i + 1, tokVoid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
*ConstExpr = 0;
|
*ConstExpr = 0;
|
||||||
}
|
}
|
||||||
@@ -4093,6 +4263,7 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
case tokComma:
|
case tokComma:
|
||||||
{
|
{
|
||||||
int oldIdxLeft, oldSpLeft;
|
int oldIdxLeft, oldSpLeft;
|
||||||
|
int retStruct = 0;
|
||||||
s = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
|
s = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
|
||||||
oldIdxLeft = *idx;
|
oldIdxLeft = *idx;
|
||||||
oldSpLeft = sp;
|
oldSpLeft = sp;
|
||||||
@@ -4103,6 +4274,8 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
exprval(idx, ExprTypeSynPtr, &constExpr[0]);
|
exprval(idx, ExprTypeSynPtr, &constExpr[0]);
|
||||||
*ConstExpr = constExpr[0] && constExpr[1];
|
*ConstExpr = constExpr[0] && constExpr[1];
|
||||||
*ExprTypeSynPtr = RightExprTypeSynPtr;
|
*ExprTypeSynPtr = RightExprTypeSynPtr;
|
||||||
|
retStruct = RightExprTypeSynPtr >= 0 && SyntaxStack[RightExprTypeSynPtr][0] == tokStructPtr;
|
||||||
|
|
||||||
if (*ConstExpr)
|
if (*ConstExpr)
|
||||||
{
|
{
|
||||||
// both subexprs are const, remove both and comma
|
// both subexprs are const, remove both and comma
|
||||||
@@ -4110,9 +4283,26 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
}
|
}
|
||||||
else if (constExpr[0])
|
else if (constExpr[0])
|
||||||
{
|
{
|
||||||
// only left subexpr is const, remove it and comma
|
// only left subexpr is const, remove it
|
||||||
del(*idx + 1, oldIdxLeft - (oldSpLeft - sp) - *idx);
|
del(*idx + 1, oldIdxLeft - (oldSpLeft - sp) - *idx);
|
||||||
del(oldIdxRight + 1 - (oldSpRight - sp), 1);
|
|
||||||
|
if (!retStruct)
|
||||||
|
// Ensure non-lvalue-ness of the result by changing comma to unary plus
|
||||||
|
// and thus hiding dereference, if any
|
||||||
|
stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUnaryPlus;
|
||||||
|
else
|
||||||
|
// However, (something, struct).member should still be allowed,
|
||||||
|
// so, comma needs to produce lvalue
|
||||||
|
del(oldIdxRight + 1 - (oldSpRight - sp), 1);
|
||||||
|
}
|
||||||
|
else if (retStruct)
|
||||||
|
{
|
||||||
|
// However, (something, struct).member should still be allowed,
|
||||||
|
// so, comma needs to produce lvalue. Swap comma and structure dereference.
|
||||||
|
int i = oldIdxRight + 1 - (oldSpRight - sp);
|
||||||
|
stack[i][0] = tokUnaryStar;
|
||||||
|
stack[i][1] = stack[i - 1][1];
|
||||||
|
stack[i - 1][0] = tokComma;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -4322,8 +4512,7 @@ int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
|
|||||||
--*idx;
|
--*idx;
|
||||||
exprval(idx, ExprTypeSynPtr, ConstExpr);
|
exprval(idx, ExprTypeSynPtr, ConstExpr);
|
||||||
|
|
||||||
if (*ExprTypeSynPtr >= 0 && SyntaxStack[*ExprTypeSynPtr][0] == '*')
|
decayArray(ExprTypeSynPtr, 0);
|
||||||
*ExprTypeSynPtr = -(*ExprTypeSynPtr + 1); // TBD!!! shouldn't this be done elsewhere?
|
|
||||||
|
|
||||||
if (*ExprTypeSynPtr >= 0 ||
|
if (*ExprTypeSynPtr >= 0 ||
|
||||||
SyntaxStack[-*ExprTypeSynPtr][0] != tokStructPtr)
|
SyntaxStack[-*ExprTypeSynPtr][0] != tokStructPtr)
|
||||||
@@ -4393,6 +4582,9 @@ STATIC
|
|||||||
int ParseExpr(int tok, int* GotUnary, int* ExprTypeSynPtr, int* ConstExpr, int* ConstVal, int option, int option2)
|
int ParseExpr(int tok, int* GotUnary, int* ExprTypeSynPtr, int* ConstExpr, int* ConstVal, int option, int option2)
|
||||||
{
|
{
|
||||||
int identFirst = tok == tokIdent;
|
int identFirst = tok == tokIdent;
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
int oldOfs = CurFxnLocalOfs;
|
||||||
|
#endif
|
||||||
*ConstVal = *ConstExpr = 0;
|
*ConstVal = *ConstExpr = 0;
|
||||||
*ExprTypeSynPtr = SymVoidSynPtr;
|
*ExprTypeSynPtr = SymVoidSynPtr;
|
||||||
|
|
||||||
@@ -4544,6 +4736,11 @@ int ParseExpr(int tok, int* GotUnary, int* ExprTypeSynPtr, int* ConstExpr, int*
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExprLevel--;
|
ExprLevel--;
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
// Reclaim stack space used by temporary structure/union objects
|
||||||
|
// returned by functions
|
||||||
|
CurFxnLocalOfs = oldOfs;
|
||||||
|
#endif
|
||||||
|
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
@@ -4570,7 +4767,7 @@ void DetermineVaListType(void)
|
|||||||
char testbuf[3][CHAR_BIT * sizeof(void*) + 1];
|
char testbuf[3][CHAR_BIT * sizeof(void*) + 1];
|
||||||
|
|
||||||
// TBD!!! This is not good. Really need the va_something macros.
|
// TBD!!! This is not good. Really need the va_something macros.
|
||||||
// Test whether va_list is a pointer to the first optional parameter or
|
// Test whether va_list is a pointer to the first optional argument or
|
||||||
// an array of one element containing said pointer
|
// an array of one element containing said pointer
|
||||||
testptr[0] = &testptr[1];
|
testptr[0] = &testptr[1];
|
||||||
testptr[1] = &testptr[0];
|
testptr[1] = &testptr[0];
|
||||||
@@ -5576,7 +5773,7 @@ int ParseBase(int tok, int base[2])
|
|||||||
}
|
}
|
||||||
else if (ParamLevel)
|
else if (ParamLevel)
|
||||||
{
|
{
|
||||||
// structure/union/enum declarations aren't supported in function parameters
|
// new structure/union/enum declarations aren't supported in function parameters
|
||||||
errorDecl();
|
errorDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5595,7 +5792,7 @@ int ParseBase(int tok, int base[2])
|
|||||||
{
|
{
|
||||||
unsigned structInfo[4], sz, alignment, tmp;
|
unsigned structInfo[4], sz, alignment, tmp;
|
||||||
|
|
||||||
// structure/union/enum declarations aren't supported in expressions and function parameters
|
// new structure/union/enum declarations aren't supported in expressions and function parameters
|
||||||
if (ExprLevel || ParamLevel)
|
if (ExprLevel || ParamLevel)
|
||||||
errorDecl();
|
errorDecl();
|
||||||
|
|
||||||
@@ -6378,11 +6575,13 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label)
|
|||||||
|
|
||||||
isFxn = SyntaxStack[lastSyntaxPtr + 1][0] == '(';
|
isFxn = SyntaxStack[lastSyntaxPtr + 1][0] == '(';
|
||||||
|
|
||||||
|
#ifdef NO_STRUCT_BY_VAL
|
||||||
if (isFxn &&
|
if (isFxn &&
|
||||||
SyntaxStack[SyntaxStackCnt - 1][0] == tokStructPtr &&
|
SyntaxStack[SyntaxStackCnt - 1][0] == tokStructPtr &&
|
||||||
SyntaxStack[SyntaxStackCnt - 2][0] == ')')
|
SyntaxStack[SyntaxStackCnt - 2][0] == ')')
|
||||||
// structure returning isn't supported currently
|
// structure returning isn't supported currently
|
||||||
errorDecl();
|
errorDecl();
|
||||||
|
#endif
|
||||||
|
|
||||||
isArray = SyntaxStack[lastSyntaxPtr + 1][0] == '[';
|
isArray = SyntaxStack[lastSyntaxPtr + 1][0] == '[';
|
||||||
isIncompleteArr = isArray && SyntaxStack[lastSyntaxPtr + 2][1] == 0;
|
isIncompleteArr = isArray && SyntaxStack[lastSyntaxPtr + 2][1] == 0;
|
||||||
@@ -6734,26 +6933,9 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label)
|
|||||||
|
|
||||||
if (isLocal)
|
if (isLocal)
|
||||||
{
|
{
|
||||||
int oldOfs;
|
|
||||||
// Let's calculate variable's relative on-stack location
|
|
||||||
oldOfs = CurFxnLocalOfs;
|
|
||||||
|
|
||||||
// Note: local vars are word-aligned on the stack
|
|
||||||
CurFxnLocalOfs = uint2int((CurFxnLocalOfs + 0u - sz) & ~(SizeOfWord - 1u));
|
|
||||||
if (CurFxnLocalOfs >= oldOfs || CurFxnLocalOfs != truncInt(CurFxnLocalOfs))
|
|
||||||
//error("ParseDecl(): Local variables take too much space\n");
|
|
||||||
errorVarSize();
|
|
||||||
#ifdef CAN_COMPILE_32BIT
|
|
||||||
if (OutputFormat == FormatSegHuge && CurFxnLocalOfs < -0x7FFF)
|
|
||||||
errorVarSize();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Now that the size of the local is certainly known,
|
// Now that the size of the local is certainly known,
|
||||||
// update its offset in the offset token
|
// update its offset in the offset token
|
||||||
SyntaxStack[lastSyntaxPtr + 1][1] = CurFxnLocalOfs;
|
SyntaxStack[lastSyntaxPtr + 1][1] = AllocLocal(sz);
|
||||||
|
|
||||||
if (CurFxnMinLocalOfs > CurFxnLocalOfs)
|
|
||||||
CurFxnMinLocalOfs = CurFxnLocalOfs;
|
|
||||||
|
|
||||||
#ifndef NO_ANNOTATIONS
|
#ifndef NO_ANNOTATIONS
|
||||||
DumpDecl(lastSyntaxPtr, 0);
|
DumpDecl(lastSyntaxPtr, 0);
|
||||||
@@ -6808,6 +6990,7 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label)
|
|||||||
// Since a local integer variable always takes as much space as a whole int,
|
// Since a local integer variable always takes as much space as a whole int,
|
||||||
// we can optimize code generation a bit by storing the initializer as an int.
|
// we can optimize code generation a bit by storing the initializer as an int.
|
||||||
// This is an old accidental optimization and I preserve it for now.
|
// This is an old accidental optimization and I preserve it for now.
|
||||||
|
// Note, this implies a little-endian CPU.
|
||||||
stack[sp - 1][1] = SizeOfWord;
|
stack[sp - 1][1] = SizeOfWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6841,6 +7024,14 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label)
|
|||||||
ParseLevel++;
|
ParseLevel++;
|
||||||
GetFxnInfo(lastSyntaxPtr, &CurFxnParamCntMin, &CurFxnParamCntMax, &CurFxnReturnExprTypeSynPtr, NULL); // get return type
|
GetFxnInfo(lastSyntaxPtr, &CurFxnParamCntMin, &CurFxnParamCntMax, &CurFxnReturnExprTypeSynPtr, NULL); // get return type
|
||||||
|
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
// Make sure the return structure type is complete
|
||||||
|
if (CurFxnReturnExprTypeSynPtr >= 0 &&
|
||||||
|
SyntaxStack[CurFxnReturnExprTypeSynPtr][0] == tokStructPtr &&
|
||||||
|
!GetDeclSize(CurFxnReturnExprTypeSynPtr, 0))
|
||||||
|
errorDecl();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (OutputFormat != FormatFlat)
|
if (OutputFormat != FormatFlat)
|
||||||
puts2(CodeHeader);
|
puts2(CodeHeader);
|
||||||
|
|
||||||
@@ -6913,8 +7104,7 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label)
|
|||||||
GenFxnEpilog();
|
GenFxnEpilog();
|
||||||
|
|
||||||
GenNumLabel(locAllocLabel + 1);
|
GenNumLabel(locAllocLabel + 1);
|
||||||
if (CurFxnMinLocalOfs)
|
GenFxnProlog2();
|
||||||
GenLocalAlloc(-CurFxnMinLocalOfs);
|
|
||||||
GenJumpUncond(locAllocLabel);
|
GenJumpUncond(locAllocLabel);
|
||||||
if (OutputFormat != FormatFlat)
|
if (OutputFormat != FormatFlat)
|
||||||
puts2(CodeFooter);
|
puts2(CodeFooter);
|
||||||
@@ -7061,11 +7251,13 @@ void ParseFxnParams(int tok)
|
|||||||
errorUnexpectedVoid();
|
errorUnexpectedVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NO_STRUCT_BY_VAL
|
||||||
if (SyntaxStack[SyntaxStackCnt - 1][0] == tokStructPtr &&
|
if (SyntaxStack[SyntaxStackCnt - 1][0] == tokStructPtr &&
|
||||||
t != '*' &&
|
t != '*' &&
|
||||||
t != ']')
|
t != ']')
|
||||||
// structure passing and returning isn't supported currently
|
// structure passing and returning isn't supported currently
|
||||||
errorDecl();
|
errorDecl();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (tok == ')')
|
if (tok == ')')
|
||||||
break;
|
break;
|
||||||
@@ -7083,6 +7275,7 @@ STATIC
|
|||||||
void AddFxnParamSymbols(int SyntaxPtr)
|
void AddFxnParamSymbols(int SyntaxPtr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
unsigned paramOfs = 2 * SizeOfWord; // ret addr, xbp
|
||||||
|
|
||||||
if (SyntaxPtr < 0 ||
|
if (SyntaxPtr < 0 ||
|
||||||
SyntaxPtr > SyntaxStackCnt - 3 ||
|
SyntaxPtr > SyntaxStackCnt - 3 ||
|
||||||
@@ -7092,11 +7285,29 @@ void AddFxnParamSymbols(int SyntaxPtr)
|
|||||||
errorInternal(6);
|
errorInternal(6);
|
||||||
|
|
||||||
CurFxnSyntaxPtr = SyntaxPtr;
|
CurFxnSyntaxPtr = SyntaxPtr;
|
||||||
CurFxnParamCnt = 0;
|
|
||||||
CurFxnParamOfs = 2 * SizeOfWord; // ret addr, xbp
|
|
||||||
CurFxnLocalOfs = 0;
|
CurFxnLocalOfs = 0;
|
||||||
CurFxnMinLocalOfs = 0;
|
CurFxnMinLocalOfs = 0;
|
||||||
|
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
if (CurFxnReturnExprTypeSynPtr >= 0 &&
|
||||||
|
SyntaxStack[CurFxnReturnExprTypeSynPtr][0] == tokStructPtr)
|
||||||
|
{
|
||||||
|
// The function returns a struct/union via an implicit param/arg (pointer to struct/union)
|
||||||
|
// before its first formal param/arg, add this implicit param/arg
|
||||||
|
#ifndef NO_ANNOTATIONS
|
||||||
|
int paramPtr = SyntaxStackCnt;
|
||||||
|
#endif
|
||||||
|
PushSyntax2(tokIdent, AddIdent("@")); // special implicit param/arg (pretval) pointing to structure receptacle
|
||||||
|
PushSyntax2(tokLocalOfs, paramOfs);
|
||||||
|
PushSyntax('*');
|
||||||
|
PushSyntax2(tokStructPtr, SyntaxStack[CurFxnReturnExprTypeSynPtr][1]);
|
||||||
|
paramOfs += SizeOfWord;
|
||||||
|
#ifndef NO_ANNOTATIONS
|
||||||
|
DumpDecl(paramPtr, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SyntaxPtr += 2; // skip "ident("
|
SyntaxPtr += 2; // skip "ident("
|
||||||
|
|
||||||
for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
|
for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
|
||||||
@@ -7105,7 +7316,7 @@ void AddFxnParamSymbols(int SyntaxPtr)
|
|||||||
|
|
||||||
if (tok == tokIdent)
|
if (tok == tokIdent)
|
||||||
{
|
{
|
||||||
int sz;
|
unsigned sz;
|
||||||
#ifndef NO_ANNOTATIONS
|
#ifndef NO_ANNOTATIONS
|
||||||
int paramPtr;
|
int paramPtr;
|
||||||
#endif
|
#endif
|
||||||
@@ -7119,19 +7330,28 @@ void AddFxnParamSymbols(int SyntaxPtr)
|
|||||||
if (SyntaxStack[i + 1][0] == tokEllipsis) // "ident(something,...)" = no more params
|
if (SyntaxStack[i + 1][0] == tokEllipsis) // "ident(something,...)" = no more params
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Make sure the parameter is not an incomplete structure
|
||||||
sz = GetDeclSize(i, 0);
|
sz = GetDeclSize(i, 0);
|
||||||
if (sz == 0)
|
if (sz == 0)
|
||||||
//error("Internal error: AddFxnParamSymbols(): GetDeclSize() = 0\n");
|
//error("Internal error: AddFxnParamSymbols(): GetDeclSize() = 0\n");
|
||||||
errorInternal(8);
|
//errorInternal(8);
|
||||||
|
errorDecl();
|
||||||
|
|
||||||
// Let's calculate this parameter's relative on-stack location
|
// Let's calculate this parameter's relative on-stack location
|
||||||
CurFxnParamOfs = (CurFxnParamOfs + SizeOfWord - 1) / SizeOfWord * SizeOfWord;
|
|
||||||
#ifndef NO_ANNOTATIONS
|
#ifndef NO_ANNOTATIONS
|
||||||
paramPtr = SyntaxStackCnt;
|
paramPtr = SyntaxStackCnt;
|
||||||
#endif
|
#endif
|
||||||
PushSyntax2(SyntaxStack[i][0], SyntaxStack[i][1]);
|
PushSyntax2(SyntaxStack[i][0], SyntaxStack[i][1]);
|
||||||
PushSyntax2(tokLocalOfs, CurFxnParamOfs);
|
PushSyntax2(tokLocalOfs, paramOfs);
|
||||||
CurFxnParamOfs += sz;
|
|
||||||
|
if (sz + SizeOfWord - 1 < sz)
|
||||||
|
errorVarSize();
|
||||||
|
sz = (sz + SizeOfWord - 1) & ~(SizeOfWord - 1u);
|
||||||
|
if (paramOfs + sz < paramOfs)
|
||||||
|
errorVarSize();
|
||||||
|
paramOfs += sz;
|
||||||
|
if (paramOfs > (unsigned)GenMaxLocalsSize())
|
||||||
|
errorVarSize();
|
||||||
|
|
||||||
// Duplicate this parameter in the symbol table
|
// Duplicate this parameter in the symbol table
|
||||||
i++;
|
i++;
|
||||||
@@ -7140,7 +7360,6 @@ void AddFxnParamSymbols(int SyntaxPtr)
|
|||||||
tok = SyntaxStack[i][0];
|
tok = SyntaxStack[i][0];
|
||||||
if (tok == tokIdent || tok == ')')
|
if (tok == tokIdent || tok == ')')
|
||||||
{
|
{
|
||||||
CurFxnParamCnt++;
|
|
||||||
#ifndef NO_ANNOTATIONS
|
#ifndef NO_ANNOTATIONS
|
||||||
DumpDecl(paramPtr, 0);
|
DumpDecl(paramPtr, 0);
|
||||||
#endif
|
#endif
|
||||||
@@ -7269,10 +7488,77 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx)
|
|||||||
errorUnexpectedToken(tok);
|
errorUnexpectedToken(tok);
|
||||||
if (gotUnary)
|
if (gotUnary)
|
||||||
//error("ParseStatement(): cannot return a value of type 'void'\n");
|
//error("ParseStatement(): cannot return a value of type 'void'\n");
|
||||||
|
#ifdef NO_STRUCT_BY_VAL
|
||||||
scalarTypeCheck(synPtr);
|
scalarTypeCheck(synPtr);
|
||||||
|
#else
|
||||||
|
nonVoidTypeCheck(synPtr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (gotUnary)
|
if (gotUnary)
|
||||||
|
{
|
||||||
|
#ifndef NO_STRUCT_BY_VAL
|
||||||
|
int structs = (synPtr >= 0 && SyntaxStack[synPtr][0] == tokStructPtr) +
|
||||||
|
(CurFxnReturnExprTypeSynPtr >= 0 && SyntaxStack[CurFxnReturnExprTypeSynPtr][0] == tokStructPtr) * 2;
|
||||||
|
|
||||||
|
if (structs)
|
||||||
|
{
|
||||||
|
if (structs != 3 ||
|
||||||
|
SyntaxStack[synPtr][1] != SyntaxStack[CurFxnReturnExprTypeSynPtr][1])
|
||||||
|
errorOpType();
|
||||||
|
|
||||||
|
// Transform "return *pstruct" into structure assignment ("*pretval = *pstruct")
|
||||||
|
// via function call "fxn(sizeof *pretval, pstruct, pretval)".
|
||||||
|
|
||||||
|
// There are a couple of differences to how this is implemented in the assignment operator:
|
||||||
|
// - the structure dereference has already been dropped from *pstruct by ParseExpr(),
|
||||||
|
// so it isn't removed here
|
||||||
|
// - we don't add the structure dereference on top of the value returned by "fxn()"
|
||||||
|
// because the return statement is not an expression that can be an operand into another
|
||||||
|
// operator
|
||||||
|
|
||||||
|
ins(0, ',');
|
||||||
|
ins2(0, tokUnaryStar, SizeOfWord); // dereference to extract the implicit param/arg (pretval) from the stack
|
||||||
|
ins2(0, tokLocalOfs, SyntaxStack[FindSymbol("@") + 1][1]); // special implicit param/arg (pretval) pointing to structure receptacle
|
||||||
|
ins2(0, '(', SizeOfWord * 3);
|
||||||
|
push(',');
|
||||||
|
push2(tokNumUint, GetDeclSize(synPtr, 0));
|
||||||
|
push(',');
|
||||||
|
if (!StructCpyLabel)
|
||||||
|
StructCpyLabel = LabelCnt++;
|
||||||
|
push2(tokIdent, AddNumericIdent__(StructCpyLabel));
|
||||||
|
push2(')', SizeOfWord * 3);
|
||||||
|
}
|
||||||
|
else // fallthrough
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// If return value (per function declaration) is a scalar type smaller than machine word,
|
||||||
|
// properly zero- or sign-extend the returned value to machine word size.
|
||||||
|
// TBD??? Move this cast to the caller?
|
||||||
|
int castSize = GetDeclSize(CurFxnReturnExprTypeSynPtr, 1);
|
||||||
|
if (castSize != SizeOfWord &&
|
||||||
|
(synPtr < 0 || castSize != GetDeclSize(synPtr, 1)))
|
||||||
|
{
|
||||||
|
switch (castSize)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
push(tokUChar);
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
push(tokSChar);
|
||||||
|
break;
|
||||||
|
#ifdef CAN_COMPILE_32BIT
|
||||||
|
case 2:
|
||||||
|
push(tokUShort);
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
push(tokShort);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
GenExpr();
|
GenExpr();
|
||||||
|
}
|
||||||
GenJumpUncond(CurFxnEpilogLabel);
|
GenJumpUncond(CurFxnEpilogLabel);
|
||||||
tok = GetToken();
|
tok = GetToken();
|
||||||
}
|
}
|
||||||
@@ -7572,7 +7858,7 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx)
|
|||||||
GenNumLabel(labelAfter);
|
GenNumLabel(labelAfter);
|
||||||
|
|
||||||
#ifndef NO_FOR_DECL
|
#ifndef NO_FOR_DECL
|
||||||
// undo any declarations done in the for() parameter set.
|
// undo any declarations made in the first clause of for
|
||||||
if (decl)
|
if (decl)
|
||||||
{
|
{
|
||||||
UndoNonLabelIdents(undoIdents); // remove all identifier names, except those of labels
|
UndoNonLabelIdents(undoIdents); // remove all identifier names, except those of labels
|
||||||
@@ -7931,7 +8217,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
GenInit();
|
GenInit();
|
||||||
|
|
||||||
// Parse the command line parameters
|
// Parse the command line arguments
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
// DONE: move code-generator-specific options to
|
// DONE: move code-generator-specific options to
|
||||||
|
|||||||
Reference in New Issue
Block a user