Merge branch 'master' into underscores

This commit is contained in:
mrdudz
2022-11-19 17:11:11 +01:00
167 changed files with 6142 additions and 2906 deletions

View File

@@ -1298,7 +1298,7 @@ static void EmitCode (EffAddr* A)
break;
case 2:
if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y | AM65_ABS_X_IND))) {
/* This is a 16 bit mode that uses an address. If in 65816,
** mode, force this address into 16 bit range to allow
** addressing inside a 64K segment.

View File

@@ -315,12 +315,41 @@ static void OpAssignBitField (const GenDesc* Gen, ExprDesc* Expr, const char* Op
} else if (Gen->Func == g_sub) {
g_dec (Flags | CF_CONST, Expr2.IVal);
} else {
if (Expr2.IVal == 0) {
/* Check for div by zero/mod by zero */
if (Gen->Func == g_div) {
Error ("Division by zero");
} else if (Gen->Func == g_mod) {
Error ("Modulo operation with zero");
if (!ED_IsUneval (Expr)) {
if (Expr2.IVal == 0) {
/* Check for div by zero/mod by zero */
if (Gen->Func == g_div) {
Warning ("Division by zero");
} else if (Gen->Func == g_mod) {
Warning ("Modulo operation with zero");
}
} else if (Gen->Func == g_asl || Gen->Func == g_asr) {
const Type* CalType = IntPromotion (Expr->Type);
unsigned ExprBits = BitSizeOf (CalType);
/* If the shift count is greater than or equal to the width of the
** promoted left operand, the behaviour is undefined according to
** the standard.
*/
if (Expr2.IVal < 0) {
Warning ("Negative shift count %ld treated as %u for %s",
Expr2.IVal,
(unsigned)Expr2.IVal & (ExprBits - 1),
GetBasicTypeName (CalType));
} else if (Expr2.IVal >= (long)ExprBits) {
Warning ("Shift count %ld >= width of %s treated as %u",
Expr2.IVal,
GetBasicTypeName (CalType),
(unsigned)Expr2.IVal & (ExprBits - 1));
}
/* Here we simply "wrap" the shift count around the width */
Expr2.IVal &= ExprBits - 1;
/* Additional check for bit-fields */
if (Expr2.IVal >= (long)Expr->Type->A.B.Width) {
Warning ("Shift count %ld >= width of bit-field", Expr2.IVal);
}
}
}
@@ -495,12 +524,42 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
} else if (Gen->Func == g_sub) {
g_dec (Flags | CF_CONST, Expr2.IVal);
} else {
if (Expr2.IVal == 0) {
/* Check for div by zero/mod by zero */
if (Gen->Func == g_div) {
Error ("Division by zero");
} else if (Gen->Func == g_mod) {
Error ("Modulo operation with zero");
if (!ED_IsUneval (Expr)) {
if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) {
/* Check for div by zero/mod by zero */
if (Gen->Func == g_div) {
Warning ("Division by zero");
} else if (Gen->Func == g_mod) {
Warning ("Modulo operation with zero");
}
} else if (Gen->Func == g_asl || Gen->Func == g_asr) {
const Type* CalType = IntPromotion (Expr->Type);
unsigned ExprBits = BitSizeOf (CalType);
/* If the shift count is greater than or equal to the width of the
** promoted left operand, the behaviour is undefined according to
** the standard.
*/
if (Expr2.IVal < 0) {
Warning ("Negative shift count %ld treated as %u for %s",
Expr2.IVal,
(unsigned)Expr2.IVal & (ExprBits - 1),
GetBasicTypeName (CalType));
} else if (Expr2.IVal >= (long)ExprBits) {
Warning ("Shift count %ld >= width of %s treated as %u",
Expr2.IVal,
GetBasicTypeName (CalType),
(unsigned)Expr2.IVal & (ExprBits - 1));
}
/* Here we simply "wrap" the shift count around the width */
Expr2.IVal &= ExprBits - 1;
/* Additional check for bit width */
if (Expr2.IVal >= (long)BitSizeOf (Expr->Type)) {
Warning ("Shift count %ld >= width of %s",
Expr2.IVal, GetBasicTypeName (Expr->Type));
}
}
}
Gen->Func (Flags | CF_CONST, Expr2.IVal);

View File

@@ -41,6 +41,7 @@
/* common */
#include "addrsize.h"
#include "attrib.h"
#include "check.h"
#include "cpu.h"
#include "shift.h"
@@ -64,7 +65,16 @@
#include "util.h"
#include "codegen.h"
/* This is a terrible hack that tries to combat the ever reoccuring issue with
Mingw and PRIXPTR - the macro should have been defined like this for us in
the first place.
NOTE: "I64u" works in the github actions now, so if your local mingw64 fails,
you probably have to update.
*/
#if defined(__MINGW64__)
#undef PRIXPTR
#define PRIXPTR "I64u"
#endif
/*****************************************************************************/
/* Helpers */
@@ -1282,34 +1292,49 @@ void g_tosint (unsigned flags)
static void g_regchar (unsigned Flags)
/* Make sure, the value in the primary register is in the range of char. Truncate if necessary */
static void g_regchar (unsigned to)
/* Treat the value in the primary register as a char with specified signedness
** and convert it to an int (whose representation is irrelevent of signedness).
*/
{
unsigned L;
AddCodeLine ("ldx #$00");
if ((Flags & CF_UNSIGNED) == 0) {
/* Sign extend */
L = GetLocalLabel();
AddCodeLine ("cmp #$80");
AddCodeLine ("bcc %s", LocalLabelName (L));
AddCodeLine ("dex");
g_defcodelabel (L);
}
/* Since char is the smallest type supported here, we never need any info
** about the original type to "promote from it". However, we have to make
** sure the entire AX contains the correct char value as an int, since we
** will almost always use the char value as an int in AX directly in code
** generation (unless CF_FORCECHAR is specified). That is to say, we don't
** need the original "from" flags for the first conversion to char, but do
** need the original "to" flags as the new "from" flags for the conversion
** to int.
*/
g_regint (to | CF_FORCECHAR);
}
void g_regint (unsigned Flags)
/* Make sure, the value in the primary register an int. Convert if necessary */
void g_regint (unsigned from)
/* Convert the value in the primary register to an int (whose representation
** is irrelevent of signedness).
*/
{
switch (Flags & CF_TYPEMASK) {
switch (from & CF_TYPEMASK) {
case CF_CHAR:
if (Flags & CF_FORCECHAR) {
/* Conversion is from char */
g_regchar (Flags);
/* If the original value was forced to use only A, it must be
** extended from char to fill AX. Otherwise nothing to do here
** since AX would already have the correct int value.
*/
if (from & CF_FORCECHAR) {
AddCodeLine ("ldx #$00");
if ((from & CF_UNSIGNED) == 0) {
/* Sign extend */
unsigned L = GetLocalLabel();
AddCodeLine ("cmp #$80");
AddCodeLine ("bcc %s", LocalLabelName (L));
AddCodeLine ("dex");
g_defcodelabel (L);
}
break;
}
/* FALLTHROUGH */
@@ -1318,21 +1343,27 @@ void g_regint (unsigned Flags)
break;
default:
typeerror (Flags);
typeerror (from);
}
}
void g_reglong (unsigned Flags)
/* Make sure, the value in the primary register a long. Convert if necessary */
void g_reglong (unsigned from)
/* Convert the value in the primary register to a long (whose representation
** is irrelevent of signedness).
*/
{
switch (Flags & CF_TYPEMASK) {
switch (from & CF_TYPEMASK) {
case CF_CHAR:
if (Flags & CF_FORCECHAR) {
/* If the original value was forced to use only A, it must be
** extended from char to long. Otherwise AX would already have
** the correct int value to be extened to long.
*/
if (from & CF_FORCECHAR) {
/* Conversion is from char */
if (Flags & CF_UNSIGNED) {
if (from & CF_UNSIGNED) {
if (IS_Get (&CodeSizeFactor) >= 200) {
AddCodeLine ("ldx #$00");
AddCodeLine ("stx sreg");
@@ -1342,18 +1373,19 @@ void g_reglong (unsigned Flags)
}
} else {
if (IS_Get (&CodeSizeFactor) >= 366) {
g_regchar (Flags);
g_regint (from);
AddCodeLine ("stx sreg");
AddCodeLine ("stx sreg+1");
} else {
AddCodeLine ("jsr along");
}
}
break;
}
/* FALLTHROUGH */
case CF_INT:
if (Flags & CF_UNSIGNED) {
if (from & CF_UNSIGNED) {
if (IS_Get (&CodeSizeFactor) >= 200) {
AddCodeLine ("ldy #$00");
AddCodeLine ("sty sreg");
@@ -1370,7 +1402,7 @@ void g_reglong (unsigned Flags)
break;
default:
typeerror (Flags);
typeerror (from);
}
}
@@ -1507,48 +1539,49 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs)
unsigned g_typecast (unsigned lhs, unsigned rhs)
/* Cast the value in the primary register to the operand size that is flagged
** by the lhs value. Return the result value.
unsigned g_typecast (unsigned to, unsigned from)
/* Cast the value in the primary register to the specified operand size and
** signedness. Return the result flags.
*/
{
/* Check if a conversion is needed */
if ((rhs & CF_CONST) == 0) {
switch (lhs & CF_TYPEMASK) {
if ((from & CF_CONST) == 0) {
switch (to & CF_TYPEMASK) {
case CF_LONG:
/* We must promote the primary register to long */
g_reglong (rhs);
/* We must promote the primary register to long in EAX */
g_reglong (from);
break;
case CF_INT:
/* We must promote the primary register to int */
g_regint (rhs);
/* We must promote the primary register to int in AX */
g_regint (from);
break;
case CF_CHAR:
/* We must truncate the primary register to char */
g_regchar (lhs);
/* We must truncate the primary register to char and then
** sign-extend it to signed int in AX.
*/
g_regchar (to);
break;
default:
typeerror (lhs);
/* Since we are switching on "to", report an error on it */
typeerror (to);
}
}
/* Do not need any other action. If the left type is int, and the primary
/* Do not need any other action. If the "to" type is int, and the primary
** register is long, it will be automagically truncated. If the right hand
** side is const, it is not located in the primary register and handled by
** the expression parser code.
*/
/* Result is const if the right hand side was const */
lhs |= (rhs & CF_CONST);
to |= (from & CF_CONST);
/* The resulting type is that of the left hand side (that's why you called
** this function :-)
*/
return lhs;
/* The resulting type is "to" (that's why you called this function :-) */
return to;
}
@@ -4561,7 +4594,7 @@ void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size)
void g_testbitfield (unsigned Flags, unsigned BitOffs, unsigned BitWidth)
void g_testbitfield (ATTR_UNUSED(unsigned Flags), unsigned BitOffs, unsigned BitWidth)
/* Test bit-field in primary. */
{
/* Since the end is inclusive and cannot be negative here, we subtract 1 from the sum */

View File

@@ -208,11 +208,15 @@ void g_toslong (unsigned flags);
void g_tosint (unsigned flags);
/* Make sure, the value on TOS is an int. Convert if necessary */
void g_regint (unsigned Flags);
/* Make sure, the value in the primary register an int. Convert if necessary */
void g_regint (unsigned from);
/* Convert the value in the primary register to an int (whose representation
** is irrelevent of signedness).
*/
void g_reglong (unsigned Flags);
/* Make sure, the value in the primary register a long. Convert if necessary */
void g_reglong (unsigned from);
/* Convert the value in the primary register to a long (whose representation
** is irrelevent of signedness).
*/
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
/* Adjust the integer operands before doing a binary operation. lhs is a flags
@@ -220,9 +224,9 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs);
** in (e)ax. The return value is the flags value for the resulting type.
*/
unsigned g_typecast (unsigned lhs, unsigned rhs);
/* Cast the value in the primary register to the operand size that is flagged
** by the lhs value. Return the result value.
unsigned g_typecast (unsigned to, unsigned from);
/* Cast the value in the primary register to the specified operand size and
** signedness. Return the result flags.
*/
void g_scale (unsigned flags, long val);

View File

@@ -399,10 +399,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
default:
/* Absolute, maybe indexed */
L = ReadToken (L, ", ", Arg, sizeof (Arg));
if (*L == ' ') {
L = SkipSpace (L+1);
}
L = ReadToken (L, ",", Arg, sizeof (Arg));
if (*L == '\0') {
/* Absolute, zeropage or branch */
if ((OPC->Info & OF_BRA) != 0) {

View File

@@ -79,7 +79,7 @@ static void Parse (void)
/* Top level parser routine. */
{
int comma;
SymEntry* Entry;
SymEntry* Sym;
FuncDesc* FuncDef = 0;
/* Initialization for deferred operations */
@@ -123,7 +123,7 @@ static void Parse (void)
}
/* Read variable defs and functions */
ParseDeclSpec (&Spec, SC_EXTERN | SC_STATIC, T_INT);
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_EXTERN | SC_STATIC);
/* Don't accept illegal storage classes */
if ((Spec.StorageClass & SC_TYPEMASK) == 0) {
@@ -142,11 +142,11 @@ static void Parse (void)
}
/* Read declarations for this type */
Entry = 0;
Sym = 0;
comma = 0;
while (1) {
Declaration Decl;
Declarator Decl;
/* Read the next declaration */
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
@@ -196,10 +196,10 @@ static void Parse (void)
}
/* Add an entry to the symbol table */
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
Sym = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
/* Add declaration attributes */
SymUseAttr (Entry, &Decl);
SymUseAttr (Sym, &Decl);
/* Reserve storage for the variable if we need to */
if (Decl.StorageClass & SC_STORAGE) {
@@ -211,11 +211,11 @@ static void Parse (void)
if (CurTok.Tok == TOK_ASSIGN) {
/* This is a definition with storage */
if (SymIsDef (Entry)) {
if (SymIsDef (Sym)) {
Error ("Global variable '%s' has already been defined",
Entry->Name);
Sym->Name);
}
Entry->Flags |= SC_DEF;
Sym->Flags |= SC_DEF;
/* We cannot initialize types of unknown size, or
** void types in ISO modes.
@@ -245,21 +245,21 @@ static void Parse (void)
}
/* Define a label */
g_defgloblabel (Entry->Name);
g_defgloblabel (Sym->Name);
/* Skip the '=' */
NextToken ();
/* Parse the initialization */
ParseInit (Entry->Type);
ParseInit (Sym->Type);
} else {
/* This is a declaration */
if (IsTypeVoid (Decl.Type)) {
/* We cannot declare variables of type void */
Error ("Illegal type for variable '%s'", Decl.Ident);
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
} else if (Size == 0 && SymIsDef (Entry) && !IsEmptiableObjectType (Decl.Type)) {
Sym->Flags &= ~(SC_STORAGE | SC_DEF);
} else if (Size == 0 && SymIsDef (Sym) && !IsEmptiableObjectType (Decl.Type)) {
/* Size is unknown. Is it an array? */
if (!IsTypeArray (Decl.Type)) {
Error ("Variable '%s' has unknown size", Decl.Ident);
@@ -286,11 +286,11 @@ static void Parse (void)
*/
const char* bssName = GetSegName (SEG_BSS);
if (Entry->V.BssName && strcmp (Entry->V.BssName, bssName) != 0) {
if (Sym->V.BssName && strcmp (Sym->V.BssName, bssName) != 0) {
Error ("Global variable '%s' already was defined in the '%s' segment.",
Entry->Name, Entry->V.BssName);
Sym->Name, Sym->V.BssName);
}
Entry->V.BssName = xstrdup (bssName);
Sym->V.BssName = xstrdup (bssName);
/* This is to make the automatical zeropage setting of the symbol
** work right.
@@ -300,9 +300,9 @@ static void Parse (void)
}
/* Make the symbol zeropage according to the segment address size */
if ((Entry->Flags & SC_STATIC) != 0) {
if ((Sym->Flags & SC_STATIC) != 0) {
if (GetSegAddrSize (GetSegName (CS->CurDSeg)) == ADDR_SIZE_ZP) {
Entry->Flags |= SC_ZEROPAGE;
Sym->Flags |= SC_ZEROPAGE;
}
}
@@ -318,7 +318,7 @@ static void Parse (void)
}
/* Function declaration? */
if (Entry && IsTypeFunc (Entry->Type)) {
if (Sym && IsTypeFunc (Sym->Type)) {
/* Function */
if (!comma) {
@@ -327,7 +327,7 @@ static void Parse (void)
NextToken ();
} else {
/* Parse the function body */
NewFunc (Entry, FuncDef);
NewFunc (Sym, FuncDef);
/* Make sure we aren't omitting any work */
CheckDeferredOpAllDone ();
@@ -478,8 +478,9 @@ void Compile (const char* FileName)
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
/* Assembly definition of uninitialized global variable */
SymEntry* Sym = GetSymType (Entry->Type);
SymEntry* TagSym = GetESUTagSym (Entry->Type);
unsigned Size = SizeOf (Entry->Type);
if (Size == 0 && IsTypeArray (Entry->Type)) {
if (GetElementCount (Entry->Type) == UNSPECIFIED) {
/* Assume array size of 1 */
@@ -488,11 +489,11 @@ void Compile (const char* FileName)
Warning ("Incomplete array '%s[]' assumed to have one element", Entry->Name);
}
Sym = GetSymType (GetElementType (Entry->Type));
TagSym = GetESUTagSym (GetElementType (Entry->Type));
}
/* For non-ESU types, Size != 0 */
if (Size != 0 || (Sym != 0 && SymIsDef (Sym))) {
if (Size != 0 || (TagSym != 0 && SymIsDef (TagSym))) {
/* Set the segment name only when it changes */
if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) {
SetSegName (SEG_BSS, Entry->V.BssName);

File diff suppressed because it is too large Load Diff

View File

@@ -239,23 +239,6 @@ extern const Type type_c_void_p[];
const char* GetBasicTypeName (const Type* T);
/* Return a const name string of the basic type.
** Return "type" for unknown basic types.
*/
const char* GetFullTypeName (const Type* T);
/* Return the full name string of the given type */
struct StrBuf* GetFullTypeNameBuf (struct StrBuf* S, const Type* T);
/* Return the full name string of the given type */
int GetQualifierTypeCodeNameBuf (struct StrBuf* S, TypeCode Qual, TypeCode IgnoredQual);
/* Return the names of the qualifiers of the type.
** Qualifiers to be ignored can be specified with the IgnoredQual flags.
** Return the count of added qualifier names.
*/
unsigned TypeLen (const Type* T);
/* Return the length of the type string */
@@ -273,17 +256,26 @@ Type* TypeAlloc (unsigned Len);
void TypeFree (Type* T);
/* Free a type string */
#if defined(HAVE_INLINE)
INLINE void CopyTypeAttr (const Type* Src, Type* Dest)
/* Copy attribute data from Src to Dest */
{
Dest->A = Src->A;
}
#else
# define CopyTypeAttr(Src, Dest) ((Dest)->A = (Src)->A)
#endif
/*****************************************************************************/
/* Type info extraction */
/*****************************************************************************/
int SignExtendChar (int C);
/* Do correct sign extension of a character */
Type* GetCharArrayType (unsigned Len);
/* Return the type for a char array of the given length */
Type* GetImplicitFuncType (void);
/* Return a type string for an inplicitly declared function */
const Type* GetStructReplacementType (const Type* SType);
/* Get a replacement type for passing a struct/union in the primary register */
/* Do correct sign extension of a character to an int */
long GetIntegerTypeMin (const Type* Type);
/* Get the smallest possible value of the integer type.
@@ -295,9 +287,51 @@ unsigned long GetIntegerTypeMax (const Type* Type);
** The type must have a known size.
*/
unsigned BitSizeOf (const Type* T);
/* Return the size (in bit-width) of a data type */
unsigned SizeOf (const Type* T);
/* Compute size (in bytes) of object represented by type array */
unsigned PSizeOf (const Type* T);
/* Compute size (in bytes) of pointee object */
unsigned CheckedBitSizeOf (const Type* T);
/* Return the size (in bit-width) of a data type. If the size is zero, emit an
** error and return some valid size instead (so the rest of the compiler
** doesn't have to work with invalid sizes).
*/
unsigned CheckedSizeOf (const Type* T);
/* Return the size (in bytes) of a data type. If the size is zero, emit an
** error and return some valid size instead (so the rest of the compiler
** doesn't have to work with invalid sizes).
*/
unsigned CheckedPSizeOf (const Type* T);
/* Return the size (in bytes) of a data type that is pointed to by a pointer.
** If the size is zero, emit an error and return some valid size instead (so
** the rest of the compiler doesn't have to work with invalid sizes).
*/
#if defined(HAVE_INLINE)
INLINE TypeCode GetQualifier (const Type* T)
/* Get the qualifier from the given type string */
{
return (T->C & T_MASK_QUAL);
}
#else
# define GetQualifier(T) ((T)->C & T_MASK_QUAL)
#endif
TypeCode GetUnderlyingTypeCode (const Type* Type);
/* Get the type code of the unqualified underlying type of TCode.
** Return TCode if it is not scalar.
*/
#if defined(HAVE_INLINE)
INLINE TypeCode UnqualifiedType (TypeCode T)
/* Return the unqalified type code */
/* Return the unqualified type code */
{
return (T & ~T_MASK_QUAL);
}
@@ -305,39 +339,94 @@ INLINE TypeCode UnqualifiedType (TypeCode T)
# define UnqualifiedType(T) ((T) & ~T_MASK_QUAL)
#endif
const Type* GetUnderlyingType (const Type* Type);
/* Get the underlying type of an enum or other integer class type */
#if defined(HAVE_INLINE)
INLINE TypeCode GetClass (const Type* T)
/* Get the class of a type string */
{
return (T->C & T_MASK_CLASS);
}
#else
# define GetClass(T) ((T)->C & T_MASK_CLASS)
#endif
TypeCode GetUnderlyingTypeCode (const Type* Type);
/* Get the type code of the unqualified underlying type of TCode.
** Return TCode if it is not scalar.
#if defined(HAVE_INLINE)
INLINE TypeCode GetSignedness (const Type* T)
/* Get the signedness of a type */
{
return (GetUnderlyingTypeCode (T) & T_MASK_SIGN);
}
#else
# define GetSignedness(T) (GetUnderlyingTypeCode (T) & T_MASK_SIGN)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetSizeModifier (const Type* T)
/* Get the size modifier of a type */
{
return (GetUnderlyingTypeCode (T) & T_MASK_SIZE);
}
#else
# define GetSizeModifier(T) (GetUnderlyingTypeCode (T) & T_MASK_SIZE)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetRawType (const Type* T)
/* Get the raw type */
{
return (T->C & T_MASK_TYPE);
}
#else
# define GetRawType(T) ((T)->C & T_MASK_TYPE)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetRawSignedness (const Type* T)
/* Get the raw signedness of a type */
{
return ((T)->C & T_MASK_SIGN);
}
#else
# define GetRawSignedness(T) ((T)->C & T_MASK_SIGN)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetRawSizeModifier (const Type* T)
/* Get the size modifier of a raw type */
{
return (T->C & T_MASK_SIZE);
}
#else
# define GetRawSizeModifier(T) ((T)->C & T_MASK_SIZE)
#endif
/*****************************************************************************/
/* Type manipulation */
/*****************************************************************************/
Type* GetImplicitFuncType (void);
/* Return a type string for an implicitly declared function */
Type* GetCharArrayType (unsigned Len);
/* Return the type for a char array of the given length */
Type* NewPointerTo (const Type* T);
/* Return a type string that is "pointer to T". The type string is allocated
** on the heap and may be freed after use.
*/
const Type* GetBitFieldChunkType (const Type* Type);
/* Get the type needed to operate on the byte chunk containing the bit-field */
unsigned SizeOf (const Type* T);
/* Compute size of object represented by type array. */
unsigned PSizeOf (const Type* T);
/* Compute size of pointer object. */
unsigned CheckedSizeOf (const Type* T);
/* Return the size of a data type. If the size is zero, emit an error and
** return some valid size instead (so the rest of the compiler doesn't have
** to work with invalid sizes).
*/
unsigned CheckedPSizeOf (const Type* T);
/* Return the size of a data type that is pointed to by a pointer. If the
** size is zero, emit an error and return some valid size instead (so the
** rest of the compiler doesn't have to work with invalid sizes).
Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth);
/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type
** string is allocated on the heap and may be freed after use.
*/
unsigned TypeOf (const Type* T);
/* Get the code generator base type of the object */
unsigned FuncTypeOf (const Type* T);
/* Get the code generator flag for calling the function */
const Type* AddressOf (const Type* T);
/* Return a type string that is "address of T". The type string is allocated
** on the heap and may be freed after use.
*/
const Type* Indirect (const Type* T);
/* Do one indirection for the given type, that is, return the type where the
@@ -349,16 +438,6 @@ Type* IndirectModifiable (Type* T);
** given type points to.
*/
Type* NewPointerTo (const Type* T);
/* Return a type string that is "pointer to T". The type string is allocated
** on the heap and may be freed after use.
*/
const Type* AddressOf (const Type* T);
/* Return a type string that is "address of T". The type string is allocated
** on the heap and may be freed after use.
*/
Type* ArrayToPtr (const Type* T);
/* Convert an array to a pointer to it's first element */
@@ -388,20 +467,22 @@ const Type* SignedType (const Type* T);
const Type* UnsignedType (const Type* T);
/* Get unsigned counterpart of the integral type */
Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth);
/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type
** string is allocated on the heap and may be freed after use.
*/
const Type* GetUnderlyingType (const Type* Type);
/* Get the underlying type of an enum or other integer class type */
const Type* GetStructReplacementType (const Type* SType);
/* Get a replacement type for passing a struct/union in the primary register */
const Type* GetBitFieldChunkType (const Type* Type);
/* Get the type needed to operate on the byte chunk containing the bit-field */
/*****************************************************************************/
/* Type Predicates */
/*****************************************************************************/
#if defined(HAVE_INLINE)
INLINE TypeCode GetRawType (const Type* T)
/* Get the raw type */
{
return (T->C & T_MASK_TYPE);
}
#else
# define GetRawType(T) ((T)->C & T_MASK_TYPE)
#endif
#if defined(HAVE_INLINE)
INLINE int IsTypeChar (const Type* T)
@@ -420,7 +501,7 @@ INLINE int IsTypeShort (const Type* T)
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT);
}
#else
# define IsTypeShort(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT)
# define IsTypeShort(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT)
#endif
#if defined(HAVE_INLINE)
@@ -585,7 +666,7 @@ INLINE int IsTypeUnion (const Type* T)
return (GetRawType (T) == T_TYPE_UNION);
}
#else
# define IsTypeUnion(T) (GetRawType (T) == T_TYPE_UNION)
# define IsTypeUnion(T) (GetRawType (T) == T_TYPE_UNION)
#endif
#if defined(HAVE_INLINE)
@@ -628,16 +709,6 @@ INLINE int IsTypeFuncPtr (const Type* T)
# define IsTypeFuncPtr(T) (IsTypePtr (T) && IsTypeFunc (T+1))
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetClass (const Type* T)
/* Get the class of a type string */
{
return (T->C & T_MASK_CLASS);
}
#else
# define GetClass(T) ((T)->C & T_MASK_CLASS)
#endif
#if defined(HAVE_INLINE)
INLINE int IsClassInt (const Type* T)
/* Return true if this is an integer type */
@@ -727,25 +798,8 @@ int IsEmptiableObjectType (const Type* T);
int HasUnknownSize (const Type* T);
/* Return true if this is an incomplete ESU type or an array of unknown size */
#if defined(HAVE_INLINE)
INLINE TypeCode GetRawSignedness (const Type* T)
/* Get the raw signedness of a type */
{
return ((T)->C & T_MASK_SIGN);
}
#else
# define GetRawSignedness(T) ((T)->C & T_MASK_SIGN)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetSignedness (const Type* T)
/* Get the signedness of a type */
{
return (GetUnderlyingTypeCode (T) & T_MASK_SIGN);
}
#else
# define GetSignedness(T) (GetUnderlyingTypeCode (T) & T_MASK_SIGN)
#endif
int TypeHasAttr (const Type* T);
/* Return true if the given type has attribute data */
#if defined(HAVE_INLINE)
INLINE int IsRawSignUnsigned (const Type* T)
@@ -787,35 +841,13 @@ INLINE int IsSignSigned (const Type* T)
# define IsSignSigned(T) (GetSignedness (T) == T_SIGN_SIGNED)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetRawSizeModifier (const Type* T)
/* Get the size modifier of a raw type */
{
return (T->C & T_MASK_SIZE);
}
#else
# define GetRawSizeModifier(T) ((T)->C & T_MASK_SIZE)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetSizeModifier (const Type* T)
/* Get the size modifier of a type */
{
return (GetUnderlyingTypeCode (T) & T_MASK_SIZE);
}
#else
# define GetSizeModifier(T) (GetUnderlyingTypeCode (T) & T_MASK_SIZE)
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode GetQualifier (const Type* T)
/* Get the qualifier from the given type string */
{
return (T->C & T_MASK_QUAL);
}
#else
# define GetQualifier(T) ((T)->C & T_MASK_QUAL)
#endif
/*****************************************************************************/
/* Qualifier helpers */
/*****************************************************************************/
#if defined(HAVE_INLINE)
INLINE int IsQualConst (const Type* T)
@@ -897,6 +929,37 @@ INLINE int IsQualCConv (const Type* T)
# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0)
#endif
TypeCode AddrSizeQualifier (unsigned AddrSize);
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
#if defined(HAVE_INLINE)
INLINE TypeCode CodeAddrSizeQualifier (void)
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */
{
return AddrSizeQualifier (CodeAddrSize);
}
#else
# define CodeAddrSizeQualifier() (AddrSizeQualifier (CodeAddrSize))
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode DataAddrSizeQualifier (void)
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */
{
return AddrSizeQualifier (DataAddrSize);
}
#else
# define DataAddrSizeQualifier() (AddrSizeQualifier (DataAddrSize))
#endif
/*****************************************************************************/
/* Function type helpers */
/*****************************************************************************/
int IsVariadicFunc (const Type* T) attribute ((const));
/* Return true if this is a function type or pointer to function type with
** variable parameter list.
@@ -924,6 +987,14 @@ Type* GetFuncReturnModifiable (Type* T) attribute ((const));
const FuncDesc* GetFuncDefinitionDesc (const Type* T) attribute ((const));
/* Get the function descriptor of the function definition */
/*****************************************************************************/
/* Array type helpers */
/*****************************************************************************/
long GetElementCount (const Type* T);
/* Get the element count of the array specified in T (which must be of
** array type).
@@ -943,47 +1014,46 @@ const Type* GetBaseElementType (const Type* T);
** the element type that is not an array.
*/
struct SymEntry* GetESUSymEntry (const Type* T) attribute ((const));
/* Return a SymEntry pointer from an enum/struct/union type */
void SetESUSymEntry (Type* T, struct SymEntry* S);
/* Set the SymEntry pointer for an enum/struct/union type */
TypeCode AddrSizeQualifier (unsigned AddrSize);
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
/*****************************************************************************/
/* ESU types helpers */
/*****************************************************************************/
#if defined(HAVE_INLINE)
INLINE TypeCode CodeAddrSizeQualifier (void)
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */
{
return AddrSizeQualifier (CodeAddrSize);
}
#else
# define CodeAddrSizeQualifier() (AddrSizeQualifier (CodeAddrSize))
#endif
#if defined(HAVE_INLINE)
INLINE TypeCode DataAddrSizeQualifier (void)
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */
{
return AddrSizeQualifier (DataAddrSize);
}
#else
# define DataAddrSizeQualifier() (AddrSizeQualifier (DataAddrSize))
#endif
int TypeHasAttr (const Type* T);
/* Return true if the given type has attribute data */
struct SymEntry* GetESUTagSym (const Type* T) attribute ((const));
/* Get the tag symbol entry of the enum/struct/union type.
** Return 0 if it is not an enum/struct/union.
*/
#if defined(HAVE_INLINE)
INLINE void CopyTypeAttr (const Type* Src, Type* Dest)
/* Copy attribute data from Src to Dest */
{
Dest->A = Src->A;
}
#else
# define CopyTypeAttr(Src, Dest) ((Dest)->A = (Src)->A)
#endif
void SetESUTagSym (Type* T, struct SymEntry* S);
/* Set the tag symbol entry of the enum/struct/union type */
/*****************************************************************************/
/* Helpers */
/*****************************************************************************/
const char* GetBasicTypeName (const Type* T);
/* Return a const name string of the basic type.
** Return "type" for unknown basic types.
*/
const char* GetFullTypeName (const Type* T);
/* Return the full name string of the given type */
struct StrBuf* GetFullTypeNameBuf (struct StrBuf* S, const Type* T);
/* Return the full name string of the given type */
int GetQualifierTypeCodeNameBuf (struct StrBuf* S, TypeCode Qual, TypeCode IgnoredQual);
/* Return the names of the qualifiers of the type.
** Qualifiers to be ignored can be specified with the IgnoredQual flags.
** Return the count of added qualifier names.
*/
void PrintType (FILE* F, const Type* T);
/* Print fulle name of the type */

View File

@@ -72,8 +72,7 @@
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
int* SignednessSpecified);
static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpecified);
/* Parse a type specifier */
@@ -84,6 +83,75 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
static unsigned ParseOneStorageClass (void)
/* Parse and return a storage class specifier */
{
unsigned StorageClass = 0;
/* Check the storage class given */
switch (CurTok.Tok) {
case TOK_EXTERN:
StorageClass = SC_EXTERN | SC_STATIC;
NextToken ();
break;
case TOK_STATIC:
StorageClass = SC_STATIC;
NextToken ();
break;
case TOK_REGISTER:
StorageClass = SC_REGISTER | SC_STATIC;
NextToken ();
break;
case TOK_AUTO:
StorageClass = SC_AUTO;
NextToken ();
break;
case TOK_TYPEDEF:
StorageClass = SC_TYPEDEF;
NextToken ();
break;
default:
break;
}
return StorageClass;
}
static int ParseStorageClass (DeclSpec* D)
/* Parse storage class specifiers. Return true if a specifier is read even if
** it was duplicated or disallowed. */
{
/* Check the storage class given */
unsigned StorageClass = ParseOneStorageClass ();
if (StorageClass == 0) {
return 0;
}
while (StorageClass != 0) {
if (D->StorageClass == 0) {
D->StorageClass = StorageClass;
} else if (D->StorageClass == StorageClass) {
Warning ("Duplicate storage class specifier");
} else {
Error ("Conflicting storage class specifier");
}
StorageClass = ParseOneStorageClass ();
}
return 1;
}
static void DuplicateQualifier (const char* Name)
/* Print an error message */
{
@@ -92,9 +160,9 @@ static void DuplicateQualifier (const char* Name)
static TypeCode OptionalQualifiers (TypeCode Allowed)
static TypeCode OptionalQualifiers (TypeCode Qualifiers, TypeCode Allowed)
/* Read type qualifiers if we have any. Allowed specifies the allowed
** qualifiers.
** qualifiers. Return any read qualifiers even if they caused errors.
*/
{
/* We start without any qualifiers */
@@ -107,7 +175,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
case TOK_CONST:
if (Allowed & T_QUAL_CONST) {
if (Q & T_QUAL_CONST) {
if (Qualifiers & T_QUAL_CONST) {
DuplicateQualifier ("const");
}
Q |= T_QUAL_CONST;
@@ -118,7 +186,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
case TOK_VOLATILE:
if (Allowed & T_QUAL_VOLATILE) {
if (Q & T_QUAL_VOLATILE) {
if (Qualifiers & T_QUAL_VOLATILE) {
DuplicateQualifier ("volatile");
}
Q |= T_QUAL_VOLATILE;
@@ -129,7 +197,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
case TOK_RESTRICT:
if (Allowed & T_QUAL_RESTRICT) {
if (Q & T_QUAL_RESTRICT) {
if (Qualifiers & T_QUAL_RESTRICT) {
DuplicateQualifier ("restrict");
}
Q |= T_QUAL_RESTRICT;
@@ -140,7 +208,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
case TOK_NEAR:
if (Allowed & T_QUAL_NEAR) {
if (Q & T_QUAL_NEAR) {
if (Qualifiers & T_QUAL_NEAR) {
DuplicateQualifier ("near");
}
Q |= T_QUAL_NEAR;
@@ -151,7 +219,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
case TOK_FAR:
if (Allowed & T_QUAL_FAR) {
if (Q & T_QUAL_FAR) {
if (Qualifiers & T_QUAL_FAR) {
DuplicateQualifier ("far");
}
Q |= T_QUAL_FAR;
@@ -162,7 +230,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
case TOK_FASTCALL:
if (Allowed & T_QUAL_FASTCALL) {
if (Q & T_QUAL_FASTCALL) {
if (Qualifiers & T_QUAL_FASTCALL) {
DuplicateQualifier ("fastcall");
}
Q |= T_QUAL_FASTCALL;
@@ -173,7 +241,7 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
case TOK_CDECL:
if (Allowed & T_QUAL_CDECL) {
if (Q & T_QUAL_CDECL) {
if (Qualifiers & T_QUAL_CDECL) {
DuplicateQualifier ("cdecl");
}
Q |= T_QUAL_CDECL;
@@ -187,13 +255,16 @@ static TypeCode OptionalQualifiers (TypeCode Allowed)
}
/* Combine with newly read qualifiers */
Qualifiers |= Q;
/* Skip the token */
NextToken ();
}
Done:
/* We cannot have more than one address size far qualifier */
switch (Q & T_QUAL_ADDRSIZE) {
switch (Qualifiers & T_QUAL_ADDRSIZE) {
case T_QUAL_NONE:
case T_QUAL_NEAR:
@@ -202,11 +273,11 @@ Done:
default:
Error ("Cannot specify more than one address size qualifier");
Q &= ~T_QUAL_ADDRSIZE;
Qualifiers &= ~T_QUAL_ADDRSIZE;
}
/* We cannot have more than one calling convention specifier */
switch (Q & T_QUAL_CCONV) {
switch (Qualifiers & T_QUAL_CCONV) {
case T_QUAL_NONE:
case T_QUAL_FASTCALL:
@@ -215,15 +286,41 @@ Done:
default:
Error ("Cannot specify more than one calling convention qualifier");
Q &= ~T_QUAL_CCONV;
Qualifiers &= ~T_QUAL_CCONV;
}
/* Return the qualifiers read */
/* Return any qualifiers just read */
return Q;
}
static void OptionalSpecifiers (DeclSpec* Spec, TypeCode* Qualifiers, typespec_t TSFlags)
/* Read storage specifiers and/or type qualifiers if we have any. Storage class
** specifiers require the corresponding typespec_t flag set to be allowed, and
** only const and volatile type qualifiers are allowed under any circumstance.
** Read storage class specifiers are output in *Spec and type qualifiers are
** output in *Qualifiers with error checking.
*/
{
TypeCode Q = T_QUAL_NONE;
int Continue;
do {
/* There may be type qualifiers *before* any storage class specifiers */
Q = OptionalQualifiers (*Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE);
*Qualifiers |= Q;
/* Parse storage class specifiers anyway then check */
Continue = ParseStorageClass (Spec);
if (Continue && (TSFlags & (TS_STORAGE_CLASS_SPEC | TS_FUNCTION_SPEC)) == 0) {
Error ("Unexpected storage class specified");
}
} while (Continue || Q != T_QUAL_NONE);
}
static void OptionalInt (void)
/* Eat an optional "int" token */
{
@@ -259,8 +356,8 @@ void InitDeclSpec (DeclSpec* D)
static void InitDeclaration (Declaration* D)
/* Initialize the Declaration struct for use */
static void InitDeclarator (Declarator* D)
/* Initialize the Declarator struct for use */
{
D->Ident[0] = '\0';
D->Type[0].C = T_END;
@@ -270,7 +367,7 @@ static void InitDeclaration (Declaration* D)
static void NeedTypeSpace (Declaration* D, unsigned Count)
static void NeedTypeSpace (Declarator* D, unsigned Count)
/* Check if there is enough space for Count type specifiers within D */
{
if (D->Index + Count >= MAXTYPELEN) {
@@ -284,8 +381,8 @@ static void NeedTypeSpace (Declaration* D, unsigned Count)
static void AddTypeToDeclaration (Declaration* D, TypeCode T)
/* Add a type specifier to the type of a declaration */
static void AddTypeCodeToDeclarator (Declarator* D, TypeCode T)
/* Add a type specifier to the type of a declarator */
{
NeedTypeSpace (D, 1);
D->Type[D->Index++].C = T;
@@ -396,48 +493,6 @@ static void FixQualifiers (Type* DataType)
static unsigned ParseOneStorageClass (void)
/* Parse and return a storage class */
{
unsigned StorageClass = 0;
/* Check the storage class given */
switch (CurTok.Tok) {
case TOK_EXTERN:
StorageClass = SC_EXTERN | SC_STATIC;
NextToken ();
break;
case TOK_STATIC:
StorageClass = SC_STATIC;
NextToken ();
break;
case TOK_REGISTER:
StorageClass = SC_REGISTER | SC_STATIC;
NextToken ();
break;
case TOK_AUTO:
StorageClass = SC_AUTO;
NextToken ();
break;
case TOK_TYPEDEF:
StorageClass = SC_TYPEDEF;
NextToken ();
break;
default:
break;
}
return StorageClass;
}
static void CheckArrayElementType (Type* DataType)
/* Check if data type consists of arrays of incomplete element types */
{
@@ -469,51 +524,24 @@ static void CheckArrayElementType (Type* DataType)
static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
/* Parse a storage class */
{
/* Assume we're using an explicit storage class */
D->Flags &= ~DS_DEF_STORAGE;
/* Check the storage class given */
D->StorageClass = ParseOneStorageClass ();
if (D->StorageClass == 0) {
/* No storage class given, use default */
D->Flags |= DS_DEF_STORAGE;
D->StorageClass = DefStorage;
} else {
unsigned StorageClass = ParseOneStorageClass ();
while (StorageClass != 0) {
if (D->StorageClass == StorageClass) {
Warning ("Duplicate storage class specifier");
} else {
Error ("Conflicting storage class specifier");
}
StorageClass = ParseOneStorageClass ();
}
}
}
static SymEntry* ESUForwardDecl (const char* Name, unsigned Flags, unsigned* DSFlags)
/* Handle an enum, struct or union forward decl */
static SymEntry* ForwardESU (const char* Name, unsigned Flags, unsigned* DSFlags)
/* Handle an enum, struct or union forward declaration */
{
/* Try to find an enum/struct/union with the given name. If there is none,
** insert a forward declaration into the current lexical level.
*/
SymEntry* Entry = FindTagSym (Name);
if (Entry == 0) {
SymEntry* TagEntry = FindTagSym (Name);
if (TagEntry == 0) {
if ((Flags & SC_ESUTYPEMASK) != SC_ENUM) {
Entry = AddStructSym (Name, Flags, 0, 0, DSFlags);
TagEntry = AddStructSym (Name, Flags, 0, 0, DSFlags);
} else {
Entry = AddEnumSym (Name, Flags, 0, 0, DSFlags);
TagEntry = AddEnumSym (Name, Flags, 0, 0, DSFlags);
}
} else if ((Entry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) {
} else if ((TagEntry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) {
/* Already defined, but not the same type class */
Error ("Symbol '%s' is already different kind", Name);
}
return Entry;
return TagEntry;
}
@@ -556,8 +584,8 @@ static const Type* GetEnumeratorType (long Min, unsigned long Max, int Signed)
static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags)
/* Process an enum declaration */
static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags)
/* Process an enum specifier */
{
SymTable* FieldTab;
long EnumVal;
@@ -574,7 +602,7 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags)
if (CurTok.Tok != TOK_LCURLY) {
/* Just a forward definition */
return ESUForwardDecl (Name, SC_ENUM, DSFlags);
return ForwardESU (Name, SC_ENUM, DSFlags);
}
/* Add a forward declaration for the enum tag in the current lexical level */
@@ -611,20 +639,20 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags)
} else {
/* Defaulted with the same signedness as the previous member's */
/* Defaulted with the same signedness as the previous member's */
IsSigned = IsSignSigned (MemberType) &&
(unsigned long)EnumVal != GetIntegerTypeMax (MemberType);
/* Enumerate. Signed integer overflow is UB but unsigned integers
** are guaranteed to wrap around.
*/
EnumVal = (long)((unsigned long)EnumVal + 1UL);
/* Enumerate by adding one to the previous value */
EnumVal = (long)(((unsigned long)EnumVal + 1UL) & 0xFFFFFFFFUL);
if (UnqualifiedType (MemberType->C) == T_ULONG && EnumVal == 0) {
/* Warn on 'unsigned long' overflow in enumeration */
Warning ("Enumerator '%s' overflows the range of '%s'",
Ident,
GetBasicTypeName (type_ulong));
/* Error since the new value cannot be represented in the
** largest unsigned integer type supported by cc65 for enum.
*/
Error ("Enumerator '%s' overflows the range of '%s'",
Ident,
GetBasicTypeName (type_ulong));
}
IsIncremented = 1;
@@ -657,11 +685,12 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags)
/* Warn if the incremented value exceeds the range of the previous
** type.
*/
if (IsIncremented &&
EnumVal >= 0 &&
if (PrevErrorCount == ErrorCount &&
IsIncremented &&
(!IsSigned || EnumVal >= 0) &&
NewType->C != UnqualifiedType (MemberType->C)) {
/* The possible overflow here can only be when EnumVal > 0 */
Warning ("Enumerator '%s' (value = %lu) is of type '%s'",
Warning ("Enumerator '%s' (value = %lu) implies type '%s'",
Ident,
(unsigned long)EnumVal,
GetBasicTypeName (NewType));
@@ -725,7 +754,7 @@ static SymEntry* ParseEnumDecl (const char* Name, unsigned* DSFlags)
static int ParseFieldWidth (Declaration* D)
static int ParseFieldWidth (Declarator* D)
/* Parse an optional field width. Returns -1 if no field width is specified,
** otherwise the width of the field.
*/
@@ -803,21 +832,19 @@ static unsigned PadWithBitField (unsigned StructSize, unsigned BitOffs)
static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon)
static unsigned AliasAnonStructFields (const Declarator* D, SymEntry* Anon)
/* Create alias fields from an anon union/struct in the current lexical level.
** The function returns the count of created aliases.
*/
{
unsigned Count = 0;
SymEntry* Field;
SymEntry* Alias;
/* Get the pointer to the symbol table entry of the anon struct */
SymEntry* Entry = GetESUSymEntry (D->Type);
/* Get the symbol table containing the fields. If it is empty, there has
** been an error before, so bail out.
*/
SymTable* Tab = Entry->V.S.SymTab;
SymTable* Tab = GetESUTagSym (D->Type)->V.S.SymTab;
if (Tab == 0) {
/* Incomplete definition - has been flagged before */
return 0;
@@ -826,24 +853,24 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon)
/* Get a pointer to the list of symbols. Then walk the list adding copies
** of the embedded struct to the current level.
*/
Entry = Tab->SymHead;
while (Entry) {
Field = Tab->SymHead;
while (Field) {
/* Enter an alias of this symbol */
if (!IsAnonName (Entry->Name)) {
Alias = AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD|SC_ALIAS, 0);
Alias->V.A.Field = Entry;
Alias->V.A.Offs = Anon->V.Offs + Entry->V.Offs;
if (!IsAnonName (Field->Name)) {
Alias = AddLocalSym (Field->Name, Field->Type, SC_STRUCTFIELD|SC_ALIAS, 0);
Alias->V.A.Field = Field;
Alias->V.A.Offs = Anon->V.Offs + Field->V.Offs;
++Count;
}
/* Currently, there can not be any attributes, but if there will be
** some in the future, we want to know this.
*/
CHECK (Entry->Attr == 0);
CHECK (Field->Attr == 0);
/* Next entry */
Entry = Entry->NextSym;
Field = Field->NextSym;
}
/* Return the count of created aliases */
@@ -852,8 +879,8 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon)
static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags)
/* Parse a union declaration. */
static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags)
/* Parse a union specifier */
{
unsigned UnionSize;
@@ -861,14 +888,14 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags)
int FieldWidth; /* Width in bits, -1 if not a bit-field */
SymTable* FieldTab;
SymEntry* UnionTagEntry;
SymEntry* Entry;
SymEntry* Field;
unsigned Flags = 0;
unsigned PrevErrorCount = ErrorCount;
if (CurTok.Tok != TOK_LCURLY) {
/* Just a forward declaration */
return ESUForwardDecl (Name, SC_UNION, DSFlags);
return ForwardESU (Name, SC_UNION, DSFlags);
}
/* Add a forward declaration for the union tag in the current lexical level */
@@ -883,19 +910,26 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags)
EnterStructLevel ();
/* Parse union fields */
UnionSize = 0;
UnionSize = 0;
while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */
DeclSpec Spec;
int SignednessSpecified = 0;
/* Check for a _Static_assert */
if (CurTok.Tok == TOK_STATIC_ASSERT) {
ParseStaticAssert ();
continue;
}
InitDeclSpec (&Spec);
ParseTypeSpec (&Spec, -1, T_QUAL_NONE, &SignednessSpecified);
ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE, &SignednessSpecified);
/* Read fields with this type */
while (1) {
Declaration Decl;
Declarator Decl;
/* Get type and name of the struct field */
ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
@@ -945,17 +979,17 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags)
AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth,
SignednessSpecified);
} else if (Decl.Ident[0] != '\0') {
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0);
Field = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0);
if (IsAnonName (Decl.Ident)) {
Entry->V.A.ANumber = UnionTagEntry->V.S.ACount++;
AliasAnonStructFields (&Decl, Entry);
Field->V.A.ANumber = UnionTagEntry->V.S.ACount++;
AliasAnonStructFields (&Decl, Field);
}
/* Check if the field itself has a flexible array member */
if (IsClassStruct (Decl.Type)) {
SymEntry* Sym = GetSymType (Decl.Type);
if (Sym && SymHasFlexibleArrayMember (Sym)) {
Entry->Flags |= SC_HAVEFAM;
SymEntry* TagEntry = GetESUTagSym (Decl.Type);
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
Field->Flags |= SC_HAVEFAM;
Flags |= SC_HAVEFAM;
}
}
@@ -992,8 +1026,8 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags)
/* Parse a struct declaration. */
static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags)
/* Parse a struct specifier */
{
unsigned StructSize;
@@ -1002,14 +1036,14 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags)
int FieldWidth; /* Width in bits, -1 if not a bit-field */
SymTable* FieldTab;
SymEntry* StructTagEntry;
SymEntry* Entry;
SymEntry* Field;
unsigned Flags = 0;
unsigned PrevErrorCount = ErrorCount;
if (CurTok.Tok != TOK_LCURLY) {
/* Just a forward declaration */
return ESUForwardDecl (Name, SC_STRUCT, DSFlags);
return ForwardESU (Name, SC_STRUCT, DSFlags);
}
/* Add a forward declaration for the struct tag in the current lexical level */
@@ -1031,6 +1065,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags)
/* Get the type of the entry */
DeclSpec Spec;
int SignednessSpecified = 0;
/* Check for a _Static_assert */
if (CurTok.Tok == TOK_STATIC_ASSERT) {
@@ -1038,14 +1073,13 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags)
continue;
}
int SignednessSpecified = 0;
InitDeclSpec (&Spec);
ParseTypeSpec (&Spec, -1, T_QUAL_NONE, &SignednessSpecified);
ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE, &SignednessSpecified);
/* Read fields with this type */
while (1) {
Declaration Decl;
Declarator Decl;
/* If we had a flexible array member before, no other fields can
** follow.
@@ -1147,17 +1181,17 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags)
StructSize += BitOffs / CHAR_BITS;
BitOffs %= CHAR_BITS;
} else if (Decl.Ident[0] != '\0') {
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize);
Field = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize);
if (IsAnonName (Decl.Ident)) {
Entry->V.A.ANumber = StructTagEntry->V.S.ACount++;
AliasAnonStructFields (&Decl, Entry);
Field->V.A.ANumber = StructTagEntry->V.S.ACount++;
AliasAnonStructFields (&Decl, Field);
}
/* Check if the field itself has a flexible array member */
if (IsClassStruct (Decl.Type)) {
SymEntry* Sym = GetSymType (Decl.Type);
if (Sym && SymHasFlexibleArrayMember (Sym)) {
Entry->Flags |= SC_HAVEFAM;
SymEntry* TagEntry = GetESUTagSym (Decl.Type);
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
Field->Flags |= SC_HAVEFAM;
Flags |= SC_HAVEFAM;
}
}
@@ -1206,15 +1240,15 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
int* SignednessSpecified)
static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpecified)
/* Parse a type specifier. Store whether one of "signed" or "unsigned" was
** specified, so bit-fields of unspecified signedness can be treated as
** unsigned; without special handling, it would be treated as signed.
*/
{
ident Ident;
SymEntry* Entry;
SymEntry* TagEntry;
TypeCode Qualifiers = T_QUAL_NONE;
if (SignednessSpecified != NULL) {
*SignednessSpecified = 0;
@@ -1223,8 +1257,8 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
/* Assume we have an explicit type */
D->Flags &= ~DS_DEF_TYPE;
/* Read type qualifiers if we have any */
Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE);
/* Read storage specifiers and/or type qualifiers if we have any */
OptionalSpecifiers (D, &Qualifiers, TSFlags);
/* Look at the data type */
switch (CurTok.Tok) {
@@ -1384,10 +1418,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
/* Remember we have an extra type decl */
D->Flags |= DS_EXTRA_TYPE;
/* Declare the union in the current scope */
Entry = ParseUnionDecl (Ident, &D->Flags);
TagEntry = ParseUnionSpec (Ident, &D->Flags);
/* Encode the union entry into the type */
D->Type[0].C = T_UNION;
SetESUSymEntry (D->Type, Entry);
SetESUTagSym (D->Type, TagEntry);
D->Type[1].C = T_END;
break;
@@ -1403,10 +1437,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
/* Remember we have an extra type decl */
D->Flags |= DS_EXTRA_TYPE;
/* Declare the struct in the current scope */
Entry = ParseStructDecl (Ident, &D->Flags);
TagEntry = ParseStructSpec (Ident, &D->Flags);
/* Encode the struct entry into the type */
D->Type[0].C = T_STRUCT;
SetESUSymEntry (D->Type, Entry);
SetESUTagSym (D->Type, TagEntry);
D->Type[1].C = T_END;
break;
@@ -1419,17 +1453,16 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
} else {
if (CurTok.Tok != TOK_LCURLY) {
Error ("Identifier expected");
} else {
AnonName (Ident, "enum");
}
AnonName (Ident, "enum");
}
/* Remember we have an extra type decl */
D->Flags |= DS_EXTRA_TYPE;
/* Parse the enum decl */
Entry = ParseEnumDecl (Ident, &D->Flags);
TagEntry = ParseEnumSpec (Ident, &D->Flags);
/* Encode the enum entry into the type */
D->Type[0].C |= T_ENUM;
SetESUSymEntry (D->Type, Entry);
SetESUTagSym (D->Type, TagEntry);
D->Type[1].C = T_END;
/* The signedness of enums is determined by the type, so say this is specified to avoid
** the int -> unsigned int handling for plain int bit-fields in AddBitField.
@@ -1442,11 +1475,11 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
case TOK_IDENT:
/* This could be a label */
if (NextTok.Tok != TOK_COLON || GetLexicalLevel () == LEX_LEVEL_STRUCT) {
Entry = FindSym (CurTok.Ident);
if (Entry && SymIsTypeDef (Entry)) {
TagEntry = FindSym (CurTok.Ident);
if (TagEntry && SymIsTypeDef (TagEntry)) {
/* It's a typedef */
NextToken ();
TypeCopy (D->Type, Entry->Type);
TypeCopy (D->Type, TagEntry->Type);
/* If it's a typedef, we should actually use whether the signedness was
** specified on the typedef, but that information has been lost. Treat the
** signedness as being specified to work around the ICE in #1267.
@@ -1471,20 +1504,21 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
/* FALL THROUGH */
default:
if (Default < 0) {
if ((TSFlags & TS_MASK_DEFAULT_TYPE) != TS_DEFAULT_TYPE_INT) {
Error ("Type expected");
D->Type[0].C = T_INT;
D->Type[1].C = T_END;
} else {
D->Flags |= DS_DEF_TYPE;
D->Type[0].C = (TypeCode) Default;
D->Type[0].C = T_INT;
D->Type[1].C = T_END;
}
break;
}
/* There may also be qualifiers *after* the initial type */
D->Type[0].C |= (Qualifiers | OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE));
/* There may also be specifiers/qualifiers *after* the initial type */
OptionalSpecifiers (D, &Qualifiers, TSFlags);
D->Type[0].C |= Qualifiers;
}
@@ -1564,7 +1598,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
DeclSpec Spec;
/* Read the declaration specifier */
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
/* We accept only auto and register as storage class specifiers, but
** we ignore all this, since we use auto anyway.
@@ -1577,7 +1611,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
/* Parse a comma separated variable list */
while (1) {
Declaration Decl;
Declarator Decl;
/* Read the parameter */
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
@@ -1591,19 +1625,19 @@ static void ParseOldStyleParamList (FuncDesc* F)
if (Decl.Ident[0] != '\0') {
/* We have a name given. Search for the symbol */
SymEntry* Sym = FindLocalSym (Decl.Ident);
if (Sym) {
SymEntry* Param = FindLocalSym (Decl.Ident);
if (Param) {
/* Check if we already changed the type for this
** parameter
*/
if (Sym->Flags & SC_DEFTYPE) {
if (Param->Flags & SC_DEFTYPE) {
/* Found it, change the default type to the one given */
ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
SymChangeType (Param, ParamTypeCvt (Decl.Type));
/* Reset the "default type" flag */
Sym->Flags &= ~SC_DEFTYPE;
Param->Flags &= ~SC_DEFTYPE;
} else {
/* Type has already been changed */
Error ("Redefinition for parameter '%s'", Sym->Name);
Error ("Redefinition for parameter '%s'", Param->Name);
}
} else {
Error ("Unknown identifier: '%s'", Decl.Ident);
@@ -1632,8 +1666,8 @@ static void ParseAnsiParamList (FuncDesc* F)
while (CurTok.Tok != TOK_RPAREN) {
DeclSpec Spec;
Declaration Decl;
SymEntry* Sym;
Declarator Decl;
SymEntry* Param;
/* Allow an ellipsis as last parameter */
if (CurTok.Tok == TOK_ELLIPSIS) {
@@ -1643,7 +1677,7 @@ static void ParseAnsiParamList (FuncDesc* F)
}
/* Read the declaration specifier */
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
/* We accept only auto and register as storage class specifiers */
if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
@@ -1681,10 +1715,10 @@ static void ParseAnsiParamList (FuncDesc* F)
ParseAttribute (&Decl);
/* Create a symbol table entry */
Sym = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
Param = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
/* Add attributes if we have any */
SymUseAttr (Sym, &Decl);
SymUseAttr (Param, &Decl);
/* If the parameter is a struct or union, emit a warning */
if (IsClassStruct (Decl.Type)) {
@@ -1713,7 +1747,7 @@ static void ParseAnsiParamList (FuncDesc* F)
static FuncDesc* ParseFuncDecl (void)
/* Parse the argument list of a function. */
/* Parse the argument list of a function with the enclosing parentheses */
{
SymEntry* Sym;
SymEntry* WrappedCall;
@@ -1725,6 +1759,9 @@ static FuncDesc* ParseFuncDecl (void)
/* Enter a new lexical level */
EnterFunctionLevel ();
/* Skip the opening paren */
NextToken ();
/* Check for several special parameter lists */
if (CurTok.Tok == TOK_RPAREN) {
/* Parameter list is empty (K&R-style) */
@@ -1782,16 +1819,16 @@ static FuncDesc* ParseFuncDecl (void)
static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Recursively process declarators. Build a type array in reverse order. */
static void DirectDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode)
/* Recursively process direct declarators. Build a type array in reverse order. */
{
/* Read optional function or pointer qualifiers. They modify the
** identifier or token to the right. For convenience, we allow a calling
** convention also for pointers here. If it's a pointer-to-function, the
** qualifier later will be transfered to the function itself. If it's a
** pointer to something else, it will be flagged as an error.
/* Read optional function or pointer qualifiers that modify the identifier
** or token to the right. For convenience, we allow a calling convention
** also for pointers here. If it's a pointer-to-function, the qualifier
** later will be transfered to the function itself. If it's a pointer to
** something else, it will be flagged as an error.
*/
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV);
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_NONE, T_QUAL_ADDRSIZE | T_QUAL_CCONV);
/* Pointer to something */
if (CurTok.Tok == TOK_STAR) {
@@ -1800,19 +1837,19 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
NextToken ();
/* Allow const, restrict, and volatile qualifiers */
Qualifiers |= OptionalQualifiers (T_QUAL_CVR);
Qualifiers |= OptionalQualifiers (Qualifiers, T_QUAL_CVR);
/* Parse the type that the pointer points to */
Declarator (Spec, D, Mode);
DirectDecl (Spec, D, Mode);
/* Add the type */
AddTypeToDeclaration (D, T_PTR | Qualifiers);
AddTypeCodeToDeclarator (D, T_PTR | Qualifiers);
return;
}
if (CurTok.Tok == TOK_LPAREN) {
NextToken ();
Declarator (Spec, D, Mode);
DirectDecl (Spec, D, Mode);
ConsumeRParen ();
} else {
/* Things depend on Mode now:
@@ -1832,7 +1869,13 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
NextToken ();
} else {
if (Mode == DM_NEED_IDENT) {
/* Some fix point tokens that are used for error recovery */
static const token_t TokenList[] = { TOK_COMMA, TOK_SEMI };
Error ("Identifier expected");
/* Try some smart error recovery */
SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0]));
}
D->Ident[0] = '\0';
}
@@ -1841,14 +1884,11 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
if (CurTok.Tok == TOK_LPAREN) {
/* Function declaration */
/* Function declarator */
FuncDesc* F;
SymEntry* PrevEntry;
/* Skip the opening paren */
NextToken ();
/* Parse the function declaration */
/* Parse the function declarator */
F = ParseFuncDecl ();
/* We cannot specify fastcall for variadic functions */
@@ -1877,7 +1917,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
Qualifiers = T_QUAL_NONE;
} else {
/* Array declaration. */
/* Array declarator */
long Size = UNSPECIFIED;
/* We cannot have any qualifiers for an array */
@@ -1941,11 +1981,11 @@ Type* ParseType (Type* T)
/* Parse a complete type specification */
{
DeclSpec Spec;
Declaration Decl;
Declarator Decl;
/* Get a type without a default */
InitDeclSpec (&Spec);
ParseTypeSpec (&Spec, -1, T_QUAL_NONE, NULL);
ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE, NULL);
/* Parse additional declarators */
ParseDecl (&Spec, &Decl, DM_NO_IDENT);
@@ -1959,19 +1999,19 @@ Type* ParseType (Type* T)
void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Parse a variable, type or function declaration */
void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode)
/* Parse a variable, type or function declarator */
{
/* Used to check if we have any errors during parsing this */
unsigned PrevErrorCount = ErrorCount;
/* Initialize the Declaration struct */
InitDeclaration (D);
/* Initialize the Declarator struct */
InitDeclarator (D);
/* Get additional declarators and the identifier */
Declarator (Spec, D, Mode);
/* Get additional derivation of the declarator and the identifier */
DirectDecl (Spec, D, Mode);
/* Add the base type. */
/* Add the base type */
NeedTypeSpace (D, TypeLen (Spec->Type) + 1); /* Bounds check */
TypeCopy (D->Type + D->Index, Spec->Type);
@@ -1989,7 +2029,7 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
D->StorageClass |= SC_FUNC;
}
/* Parse attributes for this declaration */
/* Parse attributes for this declarator */
ParseAttribute (D);
/* Check several things for function or function pointer types */
@@ -2070,22 +2110,23 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType)
void ParseDeclSpec (DeclSpec* D, typespec_t TSFlags, unsigned DefStorage)
/* Parse a declaration specification */
{
TypeCode Qualifiers;
/* Initialize the DeclSpec struct */
InitDeclSpec (D);
/* There may be qualifiers *before* the storage class specifier */
Qualifiers = OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE);
/* Assume we're using an explicit storage class */
D->Flags &= ~DS_DEF_STORAGE;
/* Now get the storage class specifier for this declaration */
ParseStorageClass (D, DefStorage);
/* Parse the type specifiers */
ParseTypeSpec (D, TSFlags | TS_STORAGE_CLASS_SPEC | TS_FUNCTION_SPEC, NULL);
/* Parse the type specifiers passing any initial type qualifiers */
ParseTypeSpec (D, DefType, Qualifiers, NULL);
/* If no explicit storage class is given, use the default */
if (D->StorageClass == 0) {
D->Flags |= DS_DEF_STORAGE;
D->StorageClass = DefStorage;
}
}

View File

@@ -53,6 +53,22 @@
/* Type specifier parser flags */
typedef enum typespec_t typespec_t;
enum typespec_t {
TS_NONE = 0x00,
/* Default type */
TS_MASK_DEFAULT_TYPE = 0x03,
TS_DEFAULT_TYPE_NONE = 0x00, /* No default type */
TS_DEFAULT_TYPE_INT = 0x01, /* Good old int */
TS_DEFAULT_TYPE_AUTO = 0x02, /* C23 type inference with auto */
/* Whether to allow certain kinds of specifiers */
TS_STORAGE_CLASS_SPEC = 0x04, /* Allow storage storage class specifiers */
TS_FUNCTION_SPEC = 0x08, /* Allow function specifiers */
};
/* Masks for the Flags field in DeclSpec */
#define DS_DEF_STORAGE 0x0001U /* Default storage class used */
#define DS_DEF_TYPE 0x0002U /* Default type used */
@@ -70,8 +86,8 @@ struct DeclSpec {
};
/* Result of ParseDecl */
typedef struct Declaration Declaration;
struct Declaration {
typedef struct Declarator Declarator;
struct Declarator {
unsigned StorageClass; /* A set of SC_xxx flags */
Type Type[MAXTYPELEN]; /* The type */
ident Ident; /* The identifier, if any*/
@@ -102,10 +118,10 @@ void InitDeclSpec (DeclSpec* D);
Type* ParseType (Type* Type);
/* Parse a complete type specification */
void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode);
/* Parse a variable, type or function declaration */
void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode);
/* Parse a variable, type or function declarator */
void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType);
void ParseDeclSpec (DeclSpec* D, typespec_t TSFlags, unsigned DefStorage);
/* Parse a declaration specification */
void CheckEmptyDecl (const DeclSpec* D);

View File

@@ -2,7 +2,7 @@
/* */
/* declattr.c */
/* */
/* Declaration attributes */
/* Declarator attributes */
/* */
/* */
/* */
@@ -55,8 +55,8 @@
/* Forwards for attribute handlers */
static void NoReturnAttr (Declaration* D);
static void UnusedAttr (Declaration* D);
static void NoReturnAttr (Declarator* D);
static void UnusedAttr (Declarator* D);
@@ -64,7 +64,7 @@ static void UnusedAttr (Declaration* D);
typedef struct AttrDesc AttrDesc;
struct AttrDesc {
const char Name[15];
void (*Handler) (Declaration*);
void (*Handler) (Declarator*);
};
static const AttrDesc AttrTable [] = {
{ "__noreturn__", NoReturnAttr },
@@ -141,8 +141,8 @@ static void ErrorSkip (void)
static void AddAttr (Declaration* D, DeclAttr* A)
/* Add an attribute to a declaration */
static void AddAttr (Declarator* D, DeclAttr* A)
/* Add an attribute to a declarator */
{
/* Allocate the list if necessary, the add the attribute */
if (D->Attributes == 0) {
@@ -159,7 +159,7 @@ static void AddAttr (Declaration* D, DeclAttr* A)
static void NoReturnAttr (Declaration* D)
static void NoReturnAttr (Declarator* D)
/* Parse the "noreturn" attribute */
{
/* Add the noreturn attribute */
@@ -168,7 +168,7 @@ static void NoReturnAttr (Declaration* D)
static void UnusedAttr (Declaration* D)
static void UnusedAttr (Declarator* D)
/* Parse the "unused" attribute */
{
/* Add the noreturn attribute */
@@ -177,7 +177,7 @@ static void UnusedAttr (Declaration* D)
void ParseAttribute (Declaration* D)
void ParseAttribute (Declarator* D)
/* Parse an additional __attribute__ modifier */
{
/* Do we have an attribute? */

View File

@@ -2,7 +2,7 @@
/* */
/* declattr.h */
/* */
/* Declaration attributes */
/* Declarator attributes */
/* */
/* */
/* */
@@ -45,7 +45,7 @@
/* Forward */
struct Declaration;
struct Declarator;
/* Supported attribute types */
typedef enum {
@@ -67,7 +67,7 @@ struct DeclAttr {
void ParseAttribute (struct Declaration* D);
void ParseAttribute (struct Declarator* D);
/* Parse an additional __attribute__ modifier */

View File

@@ -108,6 +108,36 @@ Collection DiagnosticStrBufs;
/*****************************************************************************/
/* Helpers */
/*****************************************************************************/
static const char* GetDiagnosticFileName (void)
/* Get the source file name where the diagnostic info refers to */
{
if (CurTok.LI) {
return GetInputName (CurTok.LI);
} else {
return GetCurrentFilename ();
}
}
static unsigned GetDiagnosticLineNum (void)
/* Get the source line number where the diagnostic info refers to */
{
if (CurTok.LI) {
return GetInputLine (CurTok.LI);
} else {
return GetCurrentLineNum ();
}
}
/*****************************************************************************/
/* Handling of fatal errors */
/*****************************************************************************/
@@ -119,17 +149,7 @@ void Fatal (const char* Format, ...)
{
va_list ap;
const char* FileName;
unsigned LineNum;
if (CurTok.LI) {
FileName = GetInputName (CurTok.LI);
LineNum = GetInputLine (CurTok.LI);
} else {
FileName = GetCurrentFile ();
LineNum = GetCurrentLine ();
}
fprintf (stderr, "%s:%u: Fatal: ", FileName, LineNum);
fprintf (stderr, "%s:%u: Fatal: ", GetDiagnosticFileName (), GetDiagnosticLineNum ());
va_start (ap, Format);
vfprintf (stderr, Format, ap);
@@ -145,22 +165,12 @@ void Fatal (const char* Format, ...)
void Internal (const char* Format, ...)
/* Print a message about an internal compiler error and die. */
/* Print a message about an internal compiler error and die */
{
va_list ap;
const char* FileName;
unsigned LineNum;
if (CurTok.LI) {
FileName = GetInputName (CurTok.LI);
LineNum = GetInputLine (CurTok.LI);
} else {
FileName = GetCurrentFile ();
LineNum = GetCurrentLine ();
}
fprintf (stderr, "%s:%u: Internal compiler error:\n",
FileName, LineNum);
GetDiagnosticFileName (), GetDiagnosticLineNum ());
va_start (ap, Format);
vfprintf (stderr, Format, ap);
@@ -184,7 +194,7 @@ void Internal (const char* Format, ...)
static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
/* Print an error message - internal function*/
/* Print an error message - internal function */
{
fprintf (stderr, "%s:%u: Error: ", Filename, LineNo);
vfprintf (stderr, Msg, ap);
@@ -206,7 +216,7 @@ void Error (const char* Format, ...)
{
va_list ap;
va_start (ap, Format);
IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
IntError (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap);
va_end (ap);
}
@@ -224,11 +234,11 @@ void LIError (const LineInfo* LI, const char* Format, ...)
void PPError (const char* Format, ...)
/* Print an error message. For use within the preprocessor. */
/* Print an error message. For use within the preprocessor */
{
va_list ap;
va_start (ap, Format);
IntError (GetCurrentFile(), GetCurrentLine(), Format, ap);
IntError (GetCurrentFilename(), GetCurrentLineNum(), Format, ap);
va_end (ap);
}
@@ -241,7 +251,7 @@ void PPError (const char* Format, ...)
static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
/* Print warning message - internal function. */
/* Print a warning message - internal function */
{
if (IS_Get (&WarningsAreErrors)) {
@@ -265,11 +275,11 @@ static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg,
void Warning (const char* Format, ...)
/* Print warning message. */
/* Print a warning message */
{
va_list ap;
va_start (ap, Format);
IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
IntWarning (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap);
va_end (ap);
}
@@ -287,11 +297,11 @@ void LIWarning (const LineInfo* LI, const char* Format, ...)
void PPWarning (const char* Format, ...)
/* Print warning message. For use within the preprocessor. */
/* Print a warning message. For use within the preprocessor */
{
va_list ap;
va_start (ap, Format);
IntWarning (GetCurrentFile(), GetCurrentLine(), Format, ap);
IntWarning (GetCurrentFilename(), GetCurrentLineNum(), Format, ap);
va_end (ap);
}
@@ -326,6 +336,55 @@ void ListWarnings (FILE* F)
/*****************************************************************************/
/* Handling of other infos */
/*****************************************************************************/
static void IntNote (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
/* Print a note message - internal function */
{
fprintf (stderr, "%s:%u: Note: ", Filename, LineNo);
vfprintf (stderr, Msg, ap);
fprintf (stderr, "\n");
}
void Note (const char* Format, ...)
/* Print a note message */
{
va_list ap;
va_start (ap, Format);
IntNote (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap);
va_end (ap);
}
void LINote (const LineInfo* LI, const char* Format, ...)
/* Print a note message with the line info given explicitly */
{
va_list ap;
va_start (ap, Format);
IntNote (GetInputName (LI), GetInputLine (LI), Format, ap);
va_end (ap);
}
void PPNote (const char* Format, ...)
/* Print a note message. For use within the preprocessor */
{
va_list ap;
va_start (ap, Format);
IntNote (GetCurrentFilename(), GetCurrentLineNum(), Format, ap);
va_end (ap);
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/

View File

@@ -92,7 +92,7 @@ void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)
/* Print a message about a fatal error and die */
void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
/* Print a message about an internal compiler error and die. */
/* Print a message about an internal compiler error and die */
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print an error message */
@@ -101,16 +101,16 @@ void LIError (const LineInfo* LI, const char* Format, ...) attribute ((format (p
/* Print an error message with the line info given explicitly */
void PPError (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print an error message. For use within the preprocessor. */
/* Print an error message. For use within the preprocessor */
void Warning (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print warning message. */
/* Print a warning message */
void LIWarning (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print a warning message with the line info given explicitly */
void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print warning message. For use within the preprocessor. */
/* Print a warning message. For use within the preprocessor */
IntStack* FindWarning (const char* Name);
/* Search for a warning in the WarnMap table and return a pointer to the
@@ -120,6 +120,15 @@ IntStack* FindWarning (const char* Name);
void ListWarnings (FILE* F);
/* Print a list of warning types/names to the given file */
void Note (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print a note message */
void LINote (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print a note message with the line info given explicitly */
void PPNote (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print a note message. For use within the preprocessor */
void ErrorReport (void);
/* Report errors (called at end of compile) */

View File

@@ -103,6 +103,100 @@ unsigned GlobalModeFlags (const ExprDesc* Expr)
static unsigned TypeOfBySize (unsigned Size)
/* Get the code generator replacement type of the object by its size */
{
unsigned NewType;
/* If the size is less than or equal to that of a a long, we will copy
** the struct using the primary register, otherwise we use memcpy.
*/
switch (Size) {
case 1: NewType = CF_CHAR; break;
case 2: NewType = CF_INT; break;
case 3: /* FALLTHROUGH */
case 4: NewType = CF_LONG; break;
default: NewType = CF_NONE; break;
}
return NewType;
}
unsigned TypeOf (const Type* T)
/* Get the code generator base type of the object */
{
unsigned NewType;
switch (GetUnderlyingTypeCode (T)) {
case T_SCHAR:
return CF_CHAR;
case T_UCHAR:
return CF_CHAR | CF_UNSIGNED;
case T_SHORT:
case T_INT:
return CF_INT;
case T_USHORT:
case T_UINT:
case T_PTR:
case T_ARRAY:
return CF_INT | CF_UNSIGNED;
case T_LONG:
return CF_LONG;
case T_ULONG:
return CF_LONG | CF_UNSIGNED;
case T_FLOAT:
case T_DOUBLE:
/* These two are identical in the backend */
return CF_FLOAT;
case T_FUNC:
/* Treat this as a function pointer */
return CF_INT | CF_UNSIGNED;
case T_STRUCT:
case T_UNION:
NewType = TypeOfBySize (SizeOf (T));
if (NewType != CF_NONE) {
return NewType;
}
/* Address of ... */
return CF_INT | CF_UNSIGNED;
case T_VOID:
case T_ENUM:
/* Incomplete enum type */
Error ("Incomplete type '%s'", GetFullTypeName (T));
return CF_INT;
default:
Error ("Illegal type %04lX", T->C);
return CF_INT;
}
}
unsigned FuncTypeOf (const Type* T)
/* Get the code generator flag for calling the function */
{
if (GetUnderlyingTypeCode (T) == T_FUNC) {
return (T->A.F->Flags & FD_VARIADIC) ? 0 : CF_FIXARGC;
} else {
Error ("Illegal function type %04lX", T->C);
return 0;
}
}
void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Call an expression function with checks. */
{
@@ -193,12 +287,15 @@ static unsigned typeadjust (ExprDesc* lhs, const ExprDesc* rhs, int NoPush)
void LimitExprValue (ExprDesc* Expr)
void LimitExprValue (ExprDesc* Expr, int WarnOverflow)
/* Limit the constant value of the expression to the range of its type */
{
switch (GetUnderlyingTypeCode (Expr->Type)) {
case T_INT:
case T_SHORT:
if (WarnOverflow && ((Expr->IVal < -0x8000) || (Expr->IVal > 0x7FFF))) {
Warning ("Signed integer constant overflow");
}
Expr->IVal = (int16_t)Expr->IVal;
break;
@@ -218,6 +315,9 @@ void LimitExprValue (ExprDesc* Expr)
break;
case T_SCHAR:
if (WarnOverflow && ((Expr->IVal < -0x80) || (Expr->IVal > 0x7F))) {
Warning ("Signed character constant overflow");
}
Expr->IVal = (int8_t)Expr->IVal;
break;
@@ -274,11 +374,10 @@ static unsigned ExprCheckedSizeOf (const Type* T)
/* Specially checked SizeOf() used in 'sizeof' expressions */
{
unsigned Size = SizeOf (T);
SymEntry* Sym;
if (Size == 0) {
Sym = GetSymType (T);
if (Sym == 0 || !SymIsDef (Sym)) {
SymEntry* TagSym = GetESUTagSym (T);
if (TagSym == 0 || !SymIsDef (TagSym)) {
Error ("Cannot apply 'sizeof' to incomplete type '%s'", GetFullTypeName (T));
}
}
@@ -1296,13 +1395,13 @@ static void Primary (ExprDesc* E)
/* Let's see if this is a C99-style declaration */
DeclSpec Spec;
InitDeclSpec (&Spec);
ParseDeclSpec (&Spec, -1, T_QUAL_NONE);
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_AUTO);
if (Spec.Type->C != T_END) {
Error ("Mixed declarations and code are not supported in cc65");
while (CurTok.Tok != TOK_SEMI) {
Declaration Decl;
Declarator Decl;
/* Parse one declaration */
ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
@@ -1822,7 +1921,7 @@ static void UnaryOp (ExprDesc* Expr)
Expr->Type = IntPromotion (Expr->Type);
/* Limit the calculated value to the range of its type */
LimitExprValue (Expr);
LimitExprValue (Expr, 1);
} else {
unsigned Flags;
@@ -2078,6 +2177,10 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
/* Check for const operands */
if (lconst && rconst) {
/* Evaluate the result for operands */
unsigned long Val1 = Expr->IVal;
unsigned long Val2 = Expr2.IVal;
/* Both operands are constant, remove the generated code */
RemoveCode (&Mark1);
@@ -2085,84 +2188,55 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type);
/* Handle the op differently for signed and unsigned types */
if (IsSignSigned (Expr->Type)) {
/* Evaluate the result for signed operands */
signed long Val1 = Expr->IVal;
signed long Val2 = Expr2.IVal;
switch (Tok) {
case TOK_OR:
Expr->IVal = (Val1 | Val2);
break;
case TOK_XOR:
Expr->IVal = (Val1 ^ Val2);
break;
case TOK_AND:
Expr->IVal = (Val1 & Val2);
break;
case TOK_STAR:
Expr->IVal = (Val1 * Val2);
break;
case TOK_DIV:
if (Val2 == 0) {
Error ("Division by zero");
Expr->IVal = 0x7FFFFFFF;
switch (Tok) {
case TOK_OR:
Expr->IVal = (Val1 | Val2);
break;
case TOK_XOR:
Expr->IVal = (Val1 ^ Val2);
break;
case TOK_AND:
Expr->IVal = (Val1 & Val2);
break;
case TOK_STAR:
Expr->IVal = (Val1 * Val2);
break;
case TOK_DIV:
if (Val2 == 0) {
if (!ED_IsUneval (Expr)) {
Warning ("Division by zero");
}
Expr->IVal = 0xFFFFFFFF;
} else {
/* Handle signed and unsigned operands differently */
if (IsSignSigned (Expr->Type)) {
Expr->IVal = ((long)Val1 / (long)Val2);
} else {
Expr->IVal = (Val1 / Val2);
}
break;
case TOK_MOD:
if (Val2 == 0) {
Error ("Modulo operation with zero");
Expr->IVal = 0;
}
break;
case TOK_MOD:
if (Val2 == 0) {
if (!ED_IsUneval (Expr)) {
Warning ("Modulo operation with zero");
}
Expr->IVal = 0;
} else {
/* Handle signed and unsigned operands differently */
if (IsSignSigned (Expr->Type)) {
Expr->IVal = ((long)Val1 % (long)Val2);
} else {
Expr->IVal = (Val1 % Val2);
}
break;
default:
Internal ("hie_internal: got token 0x%X\n", Tok);
}
} else {
/* Evaluate the result for unsigned operands */
unsigned long Val1 = Expr->IVal;
unsigned long Val2 = Expr2.IVal;
switch (Tok) {
case TOK_OR:
Expr->IVal = (Val1 | Val2);
break;
case TOK_XOR:
Expr->IVal = (Val1 ^ Val2);
break;
case TOK_AND:
Expr->IVal = (Val1 & Val2);
break;
case TOK_STAR:
Expr->IVal = (Val1 * Val2);
break;
case TOK_DIV:
if (Val2 == 0) {
Error ("Division by zero");
Expr->IVal = 0xFFFFFFFF;
} else {
Expr->IVal = (Val1 / Val2);
}
break;
case TOK_MOD:
if (Val2 == 0) {
Error ("Modulo operation with zero");
Expr->IVal = 0;
} else {
Expr->IVal = (Val1 % Val2);
}
break;
default:
Internal ("hie_internal: got token 0x%X\n", Tok);
}
}
break;
default:
Internal ("hie_internal: got token 0x%X\n", Tok);
}
/* Limit the calculated value to the range of its type */
LimitExprValue (Expr);
LimitExprValue (Expr, 1);
} else if (lconst && (Gen->Flags & GEN_COMM) && !rconst) {
/* If the LHS constant is an int that fits into an unsigned char, change the
@@ -2215,10 +2289,12 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
/* Second value is constant - check for div */
type |= CF_CONST;
rtype |= CF_CONST;
if (Tok == TOK_DIV && Expr2.IVal == 0) {
Error ("Division by zero");
} else if (Tok == TOK_MOD && Expr2.IVal == 0) {
Error ("Modulo operation with zero");
if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) {
if (Tok == TOK_DIV) {
Warning ("Division by zero");
} else if (Tok == TOK_MOD) {
Warning ("Modulo operation with zero");
}
}
if ((Gen->Flags & GEN_NOPUSH) != 0) {
RemoveCode (&Mark2);
@@ -2789,7 +2865,7 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef)
Expr->Type = rhst;
} else {
/* Limit the calculated value to the range of its type */
LimitExprValue (Expr);
LimitExprValue (Expr, 1);
}
/* The result is always an rvalue */
@@ -3260,7 +3336,7 @@ static void parsesub (ExprDesc* Expr)
/* Just adjust the result type */
Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type);
/* And limit the calculated value to the range of it */
LimitExprValue (Expr);
LimitExprValue (Expr, 1);
}
/* The result is always an rvalue */
ED_MarkExprAsRVal (Expr);
@@ -3814,17 +3890,6 @@ static void hieQuest (ExprDesc* Expr)
ED_Init (&Expr3);
Expr3.Flags = Flags;
NextToken ();
/* Convert non-integer constant to boolean constant, so that we may just
** check it in the same way.
*/
if (ED_IsConstTrue (Expr)) {
ED_MakeConstBool (Expr, 1);
} else if (ED_IsConstFalse (Expr)) {
ED_MakeConstBool (Expr, 0);
}
if (!ConstantCond) {
/* Condition codes not set, request a test */
ED_RequireTest (Expr);
@@ -3836,6 +3901,15 @@ static void hieQuest (ExprDesc* Expr)
FalseLab = GetLocalLabel ();
g_falsejump (CF_NONE, FalseLab);
} else {
/* Convert non-integer constant to boolean constant, so that we
** may just check it in an easier way later.
*/
if (ED_IsConstTrue (Expr)) {
ED_MakeConstBool (Expr, 1);
} else if (ED_IsConstFalse (Expr)) {
ED_MakeConstBool (Expr, 0);
}
/* Constant boolean subexpression could still have deferred inc/dec
** operations, so just flush their side-effects at this sequence point.
*/
@@ -3844,9 +3918,18 @@ static void hieQuest (ExprDesc* Expr)
if (Expr->IVal == 0) {
/* Remember the current code position */
GetCodePos (&SkippedBranch);
/* Expr2 is unevaluated when the condition is false */
Expr2.Flags |= E_EVAL_UNEVAL;
} else {
/* Expr3 is unevaluated when the condition is true */
Expr3.Flags |= E_EVAL_UNEVAL;
}
}
/* Skip the question mark */
NextToken ();
/* Parse second expression. Remember for later if it is a NULL pointer
** expression, then load it into the primary.
*/
@@ -3863,9 +3946,9 @@ static void hieQuest (ExprDesc* Expr)
ED_FinalizeRValLoad (&Expr2);
} else {
/* Constant boolean subexpression could still have deferred inc/
** dec operations, so just flush their side-effects at this
** sequence point.
/* Constant subexpression could still have deferred inc/dec
** operations, so just flush their side-effects at this sequence
** point.
*/
DoDeferred (SQP_KEEP_NONE, &Expr2);
}
@@ -3878,30 +3961,26 @@ static void hieQuest (ExprDesc* Expr)
/* Jump around the evaluation of the third expression */
TrueLab = GetLocalLabel ();
ConsumeColon ();
g_jump (TrueLab);
/* Jump here if the first expression was false */
g_defcodelabel (FalseLab);
} else {
if (Expr->IVal == 0) {
/* Expr2 is unevaluated when the condition is false */
Expr2.Flags |= E_EVAL_UNEVAL;
/* Remove the load code of Expr2 */
RemoveCode (&SkippedBranch);
} else {
/* Remember the current code position */
GetCodePos (&SkippedBranch);
}
ConsumeColon();
}
ConsumeColon ();
/* Parse third expression. Remember for later if it is a NULL pointer
** expression, then load it into the primary.
*/
ExprWithCheck (hie1, &Expr3);
ExprWithCheck (hieQuest, &Expr3);
Expr3IsNULL = ED_IsNullPtr (&Expr3);
if (!IsTypeVoid (Expr3.Type) &&
ED_YetToLoad (&Expr3) &&
@@ -3914,18 +3993,15 @@ static void hieQuest (ExprDesc* Expr)
ED_FinalizeRValLoad (&Expr3);
} else {
/* Constant boolean subexpression could still have deferred inc/
** dec operations, so just flush their side-effects at this
** sequence point.
/* Constant subexpression could still have deferred inc/dec
** operations, so just flush their side-effects at this sequence
** point.
*/
DoDeferred (SQP_KEEP_NONE, &Expr3);
}
Expr3.Type = PtrConversion (Expr3.Type);
if (ConstantCond && Expr->IVal != 0) {
/* Expr3 is unevaluated when the condition is true */
Expr3.Flags |= E_EVAL_UNEVAL;
/* Remove the load code of Expr3 */
RemoveCode (&SkippedBranch);
}
@@ -4030,6 +4106,8 @@ static void hieQuest (ExprDesc* Expr)
} else {
*Expr = Expr3;
}
/* The result expression is always an rvalue */
ED_MarkExprAsRVal (Expr);
}
/* Setup the target expression */

View File

@@ -51,6 +51,12 @@ typedef struct GenDesc {
unsigned GlobalModeFlags (const ExprDesc* Expr);
/* Return the addressing mode flags for the given expression */
unsigned TypeOf (const Type* T);
/* Get the code generator base type of the object */
unsigned FuncTypeOf (const Type* T);
/* Get the code generator flag for calling the function */
void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Call an expression function with checks. */
@@ -59,7 +65,7 @@ void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr);
** generated code.
*/
void LimitExprValue (ExprDesc* Expr);
void LimitExprValue (ExprDesc* Expr, int WarnOverflow);
/* Limit the constant value of the expression to the range of its type */
void PushAddr (const ExprDesc* Expr);

View File

@@ -67,74 +67,9 @@ ExprDesc* ED_Init (ExprDesc* Expr)
#if !defined(HAVE_INLINE)
int ED_IsLocQuasiConst (const ExprDesc* Expr)
/* Return true if the expression is a constant location of some sort or on the
** stack.
*/
{
return ED_IsLocConst (Expr) || ED_IsLocStack (Expr);
}
#endif
#if !defined(HAVE_INLINE)
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
{
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
}
#endif
#if !defined(HAVE_INLINE)
int ED_IsIndExpr (const ExprDesc* Expr)
/* Check if the expression is a reference to its value */
{
return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr);
}
#endif
int ED_YetToLoad (const ExprDesc* Expr)
/* Check if the expression needs to be loaded somehow. */
{
return ED_NeedsPrimary (Expr) ||
ED_YetToTest (Expr) ||
(ED_IsLVal (Expr) && IsQualVolatile (Expr->Type));
}
void ED_MarkForUneval (ExprDesc* Expr)
/* Mark the expression as not to be evaluated */
{
Expr->Flags = (Expr->Flags & ~E_MASK_EVAL) | E_EVAL_UNEVAL;
}
void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End)
/* Set the code range for this expression */
{
Expr->Flags |= E_HAVE_MARKS;
Expr->Start = *Start;
Expr->End = *End;
}
int ED_CodeRangeIsEmpty (const ExprDesc* Expr)
/* Return true if no code was output for this expression */
{
/* We must have code marks */
PRECONDITION (Expr->Flags & E_HAVE_MARKS);
return CodeRangeIsEmpty (&Expr->Start, &Expr->End);
}
/*****************************************************************************/
/* Info Extraction */
/*****************************************************************************/
@@ -214,132 +149,51 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type)
/* Replace Expr with an absolute const with the given value and type */
/*****************************************************************************/
/* Predicates */
/*****************************************************************************/
#if !defined(HAVE_INLINE)
int ED_IsLocQuasiConst (const ExprDesc* Expr)
/* Return true if the expression is a constant location of some sort or on the
** stack.
*/
{
Expr->Type = Type;
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_MASK_KEEP_MAKE);
Expr->Name = 0;
Expr->Sym = 0;
Expr->IVal = Value;
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
return ED_IsLocConst (Expr) || ED_IsLocStack (Expr);
}
#endif
ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
/* Replace Expr with a constant integer expression with the given value */
#if !defined(HAVE_INLINE)
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
{
Expr->Type = type_int;
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_MASK_KEEP_MAKE);
Expr->Name = 0;
Expr->Sym = 0;
Expr->IVal = Value;
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
}
#endif
ExprDesc* ED_MakeConstBool (ExprDesc* Expr, long Value)
/* Replace Expr with a constant boolean expression with the given value */
#if !defined(HAVE_INLINE)
int ED_IsIndExpr (const ExprDesc* Expr)
/* Check if the expression is a reference to its value */
{
Expr->Sym = 0;
Expr->Type = type_bool;
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_MASK_KEEP_MAKE);
Expr->Name = 0;
Expr->IVal = Value;
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
}
#endif
ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr)
/* Finalize the result of LoadExpr to be an rvalue in the primary register */
int ED_YetToLoad (const ExprDesc* Expr)
/* Check if the expression needs to be loaded somehow. */
{
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_ADDRESS_OF);
Expr->Flags &= ~E_CC_SET;
Expr->Flags |= (E_LOC_PRIMARY | E_RTYPE_RVAL);
Expr->Sym = 0;
Expr->Name = 0;
Expr->IVal = 0; /* No offset */
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
}
ExprDesc* ED_AddrExpr (ExprDesc* Expr)
/* Take address of Expr. The result is always an rvalue */
{
switch (Expr->Flags & E_MASK_LOC) {
case E_LOC_NONE:
Error ("Cannot get the address of a numeric constant");
break;
case E_LOC_EXPR:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_ADDRESS_OF | E_LOC_PRIMARY | E_RTYPE_RVAL;
break;
default:
if ((Expr->Flags & E_ADDRESS_OF) == 0) {
Expr->Flags &= ~E_MASK_RTYPE;
Expr->Flags |= E_ADDRESS_OF | E_RTYPE_RVAL;
} else {
/* Due to the way we handle arrays, this may happen if we take
** the address of a pointer to an array element.
*/
if (!IsTypePtr (Expr->Type)) {
Error ("Cannot get the address of an address");
}
Expr->Flags &= ~E_MASK_RTYPE;
Expr->Flags |= E_RTYPE_RVAL;
}
break;
}
return Expr;
}
ExprDesc* ED_IndExpr (ExprDesc* Expr)
/* Dereference Expr */
{
switch (Expr->Flags & E_MASK_LOC) {
case E_LOC_NONE:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_ABS | E_RTYPE_LVAL;
break;
case E_LOC_PRIMARY:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_EXPR | E_RTYPE_LVAL;
break;
default:
if ((Expr->Flags & E_ADDRESS_OF) != 0) {
Expr->Flags &= ~(E_MASK_RTYPE | E_ADDRESS_OF);
Expr->Flags |= E_RTYPE_LVAL;
} else {
/* Due to the limitation of LoadExpr, this may happen after we
** have loaded the value from a referenced address, in which
** case the content in the primary no longer refers to the
** original address. We simply mark this as E_LOC_EXPR so that
** some info about the original location can be retained.
** If it's really meant to dereference a "pointer value", it
** should be done in two steps where the pointervalue should
** be the manually loaded first before a call into this, and
** the offset should be manually cleared somewhere outside.
*/
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_EXPR | E_RTYPE_LVAL;
}
break;
}
return Expr;
return ED_NeedsPrimary (Expr) ||
ED_YetToTest (Expr) ||
(ED_IsLVal (Expr) && IsQualVolatile (Expr->Type));
}
@@ -427,6 +281,7 @@ int ED_IsQuasiConst (const ExprDesc* Expr)
}
int ED_IsConstAddr (const ExprDesc* Expr)
/* Return true if the expression denotes a constant address of some sort. This
** can be the address of a global variable (maybe with offset) or similar.
@@ -472,6 +327,166 @@ int ED_IsBool (const ExprDesc* Expr)
/*****************************************************************************/
/* Manipulation */
/*****************************************************************************/
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type)
/* Replace Expr with an absolute const with the given value and type */
{
Expr->Type = Type;
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_MASK_KEEP_MAKE);
Expr->Name = 0;
Expr->Sym = 0;
Expr->IVal = Value;
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
}
ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
/* Replace Expr with a constant integer expression with the given value */
{
Expr->Type = type_int;
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_MASK_KEEP_MAKE);
Expr->Name = 0;
Expr->Sym = 0;
Expr->IVal = Value;
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
}
ExprDesc* ED_MakeConstBool (ExprDesc* Expr, long Value)
/* Replace Expr with a constant boolean expression with the given value */
{
Expr->Sym = 0;
Expr->Type = type_bool;
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_MASK_KEEP_MAKE);
Expr->Name = 0;
Expr->IVal = Value;
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
}
ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr)
/* Finalize the result of LoadExpr to be an rvalue in the primary register */
{
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_ADDRESS_OF);
Expr->Flags &= ~E_CC_SET;
Expr->Flags |= (E_LOC_PRIMARY | E_RTYPE_RVAL);
Expr->Sym = 0;
Expr->Name = 0;
Expr->IVal = 0; /* No offset */
memset (&Expr->V, 0, sizeof (Expr->V));
return Expr;
}
ExprDesc* ED_AddrExpr (ExprDesc* Expr)
/* Take address of Expr. The result is always an rvalue */
{
switch (Expr->Flags & E_MASK_LOC) {
case E_LOC_NONE:
Error ("Cannot get the address of a numeric constant");
break;
case E_LOC_EXPR:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_PRIMARY | E_RTYPE_RVAL;
break;
default:
if ((Expr->Flags & E_ADDRESS_OF) == 0) {
Expr->Flags &= ~E_MASK_RTYPE;
Expr->Flags |= E_ADDRESS_OF | E_RTYPE_RVAL;
} else {
/* Due to the way we handle arrays, this may happen if we take
** the address of a pointer to an array element.
*/
if (!IsTypePtr (Expr->Type)) {
Error ("Cannot get the address of an address");
}
Expr->Flags &= ~E_MASK_RTYPE;
Expr->Flags |= E_RTYPE_RVAL;
}
break;
}
return Expr;
}
ExprDesc* ED_IndExpr (ExprDesc* Expr)
/* Dereference Expr */
{
switch (Expr->Flags & E_MASK_LOC) {
case E_LOC_NONE:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_ABS | E_RTYPE_LVAL;
break;
case E_LOC_PRIMARY:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_EXPR | E_RTYPE_LVAL;
break;
default:
if ((Expr->Flags & E_ADDRESS_OF) != 0) {
Expr->Flags &= ~(E_MASK_RTYPE | E_ADDRESS_OF);
Expr->Flags |= E_RTYPE_LVAL;
} else {
/* Due to the limitation of LoadExpr, this may happen after we
** have loaded the value from a referenced address, in which
** case the content in the primary no longer refers to the
** original address. We simply mark this as E_LOC_EXPR so that
** some info about the original location can be retained.
** If it's really meant to dereference a "pointer value", it
** should be done in two steps where the pointer value should
** be the manually loaded first before a call into this, and
** the offset should be manually cleared somewhere outside.
*/
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_EXPR | E_RTYPE_LVAL;
}
break;
}
return Expr;
}
void ED_MarkForUneval (ExprDesc* Expr)
/* Mark the expression as not to be evaluated */
{
Expr->Flags = (Expr->Flags & ~E_MASK_EVAL) | E_EVAL_UNEVAL;
}
const Type* ReplaceType (ExprDesc* Expr, const Type* NewType)
/* Replace the type of Expr by a copy of Newtype and return the old type string */
{
const Type* OldType = Expr->Type;
Expr->Type = TypeDup (NewType);
return OldType;
}
/*****************************************************************************/
/* Other Helpers */
/*****************************************************************************/
void PrintExprDesc (FILE* F, ExprDesc* E)
/* Print an ExprDesc */
{
@@ -576,10 +591,21 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
const Type* ReplaceType (ExprDesc* Expr, const Type* NewType)
/* Replace the type of Expr by a copy of Newtype and return the old type string */
void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End)
/* Set the code range for this expression */
{
const Type* OldType = Expr->Type;
Expr->Type = TypeDup (NewType);
return OldType;
Expr->Flags |= E_HAVE_MARKS;
Expr->Start = *Start;
Expr->End = *End;
}
int ED_CodeRangeIsEmpty (const ExprDesc* Expr)
/* Return true if no code was output for this expression */
{
/* We must have code marks */
PRECONDITION (Expr->Flags & E_HAVE_MARKS);
return CodeRangeIsEmpty (&Expr->Start, &Expr->End);
}

View File

@@ -227,6 +227,14 @@ struct ExprDesc {
ExprDesc* ED_Init (ExprDesc* Expr);
/* Initialize an ExprDesc */
/*****************************************************************************/
/* Info Extraction */
/*****************************************************************************/
#if defined(HAVE_INLINE)
INLINE int ED_GetLoc (const ExprDesc* Expr)
/* Return the location flags from the expression */
@@ -237,6 +245,35 @@ INLINE int ED_GetLoc (const ExprDesc* Expr)
# define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_GetNeeds (const ExprDesc* Expr)
/* Get flags about what the expression needs. */
{
return (Expr->Flags & E_MASK_NEED);
}
#else
# define ED_GetNeeds(Expr) ((Expr)->Flags & E_MASK_NEED)
#endif
const char* ED_GetLabelName (const ExprDesc* Expr, long Offs);
/* Return the assembler label name of the given expression. Beware: This
** function may use a static buffer, so the name may get "lost" on the second
** call to the function.
*/
int ED_GetStackOffs (const ExprDesc* Expr, int Offs);
/* Get the stack offset of an address on the stack in Expr taking into account
** an additional offset in Offs.
*/
/*****************************************************************************/
/* Predicates */
/*****************************************************************************/
#if defined(HAVE_INLINE)
INLINE int ED_IsLocNone (const ExprDesc* Expr)
/* Return true if the expression is an absolute value */
@@ -279,7 +316,7 @@ INLINE int ED_IsLocStack (const ExprDesc* Expr)
#if defined(HAVE_INLINE)
INLINE int ED_IsLocPrimary (const ExprDesc* Expr)
/* Return true if the expression is an expression in the register pseudo variable */
/* Return true if the expression is an expression in the primary */
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY;
}
@@ -289,7 +326,7 @@ INLINE int ED_IsLocPrimary (const ExprDesc* Expr)
#if defined(HAVE_INLINE)
INLINE int ED_IsLocExpr (const ExprDesc* Expr)
/* Return true if the expression is an expression in the primary */
/* Return true if the expression is an expression referenced in the primary */
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR;
}
@@ -333,33 +370,14 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr);
#endif
#if defined(HAVE_INLINE)
INLINE void ED_RequireTest (ExprDesc* Expr)
/* Mark the expression for a test. */
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
{
Expr->Flags |= E_NEED_TEST;
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
}
#else
# define ED_RequireTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_RequireNoTest (ExprDesc* Expr)
/* Mark the expression not for a test. */
{
Expr->Flags &= ~E_NEED_TEST;
}
#else
# define ED_RequireNoTest(Expr) do { (Expr)->Flags &= ~E_NEED_TEST; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_GetNeeds (const ExprDesc* Expr)
/* Get flags about what the expression needs. */
{
return (Expr->Flags & E_MASK_NEED);
}
#else
# define ED_GetNeeds(Expr) ((Expr)->Flags & E_MASK_NEED)
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr);
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
#endif
#if defined(HAVE_INLINE)
@@ -382,27 +400,6 @@ INLINE int ED_NeedsTest (const ExprDesc* Expr)
# define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_YetToTest (const ExprDesc* Expr)
/* Check if the expression needs to be tested but not yet. */
{
return ((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST;
}
#else
# define ED_YetToTest(Expr) (((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_TestDone (ExprDesc* Expr)
/* Mark the expression as tested and condition codes set. */
{
Expr->Flags |= E_CC_SET;
}
#else
# define ED_TestDone(Expr) \
do { (Expr)->Flags |= E_CC_SET; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsTested (const ExprDesc* Expr)
/* Check if the expression has set the condition codes. */
@@ -414,13 +411,13 @@ INLINE int ED_IsTested (const ExprDesc* Expr)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MarkAsUntested (ExprDesc* Expr)
/* Mark the expression as not tested (condition codes not set). */
INLINE int ED_YetToTest (const ExprDesc* Expr)
/* Check if the expression needs to be tested but not yet. */
{
Expr->Flags &= ~E_CC_SET;
return ((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST;
}
#else
# define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0)
# define ED_YetToTest(Expr) (((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST)
#endif
#if defined(HAVE_INLINE)
@@ -448,9 +445,6 @@ INLINE int ED_NeedsConst (const ExprDesc* Expr)
# define ED_NeedsConst(Expr) (((Expr)->Flags & E_EVAL_IMMUTABLE_RESULT) == E_EVAL_IMMUTABLE_RESULT)
#endif
void ED_MarkForUneval (ExprDesc* Expr);
/* Mark the expression as not to be evaluated */
#if defined(HAVE_INLINE)
INLINE int ED_IsUneval (const ExprDesc* Expr)
/* Check if the expression is not to be evaluated */
@@ -471,27 +465,6 @@ INLINE int ED_MayHaveNoEffect (const ExprDesc* Expr)
# define ED_MayHaveNoEffect(Expr) (((Expr)->Flags & E_EVAL_MAYBE_UNUSED) == E_EVAL_MAYBE_UNUSED)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr)
/* Propagate viral flags from subexpression */
{
Expr->Flags |= SubExpr->Flags & E_MASK_VIRAL;
}
#else
# define ED_PropagateFrom(Expr, SubExpr) (void)((Expr)->Flags |= (SubExpr)->Flags & E_MASK_VIRAL)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
{
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
}
#else
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr);
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsAddrExpr (const ExprDesc* Expr)
/* Check if the expression is taken address of instead of its value.
@@ -507,42 +480,14 @@ INLINE int ED_IsAddrExpr (const ExprDesc* Expr)
INLINE int ED_IsIndExpr (const ExprDesc* Expr)
/* Check if the expression is a reference to its value */
{
return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr);
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
}
#else
int ED_IsIndExpr (const ExprDesc* Expr);
/* Check if the expression is a reference to its value */
#endif
void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End);
/* Set the code range for this expression */
int ED_CodeRangeIsEmpty (const ExprDesc* Expr);
/* Return true if no code was output for this expression */
const char* ED_GetLabelName (const ExprDesc* Expr, long Offs);
/* Return the assembler label name of the given expression. Beware: This
** function may use a static buffer, so the name may get "lost" on the second
** call to the function.
*/
int ED_GetStackOffs (const ExprDesc* Expr, int Offs);
/* Get the stack offset of an address on the stack in Expr taking into account
** an additional offset in Offs.
*/
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type);
/* Replace Expr with an absolute const with the given value and type */
ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value);
/* Replace Expr with an constant integer with the given value */
ExprDesc* ED_MakeConstBool (ExprDesc* Expr, long Value);
/* Replace Expr with a constant boolean expression with the given value */
ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr);
/* Finalize the result of LoadExpr to be an rvalue in the primary register */
#if defined(HAVE_INLINE)
INLINE int ED_IsLVal (const ExprDesc* Expr)
/* Return true if the expression is a reference */
@@ -563,40 +508,6 @@ INLINE int ED_IsRVal (const ExprDesc* Expr)
# define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MarkExprAsLVal (ExprDesc* Expr)
/* Mark the expression as an lvalue.
** HINT: Consider using ED_IndExpr instead of this, unless you know what
** consequence there will be, as there are both a big part in the code
** assuming rvalue = const and a big part assuming rvalue = address.
*/
{
Expr->Flags |= E_RTYPE_LVAL;
}
#else
# define ED_MarkExprAsLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MarkExprAsRVal (ExprDesc* Expr)
/* Mark the expression as an rvalue.
** HINT: Consider using ED_AddrExpr instead of this, unless you know what
** consequence there will be, as there are both a big part in the code
** assuming rvalue = const and a big part assuming rvalue = address.
*/
{
Expr->Flags &= ~E_RTYPE_LVAL;
}
#else
# define ED_MarkExprAsRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
#endif
ExprDesc* ED_AddrExpr (ExprDesc* Expr);
/* Take address of Expr */
ExprDesc* ED_IndExpr (ExprDesc* Expr);
/* Dereference Expr */
#if defined(HAVE_INLINE)
INLINE int ED_IsAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a numeric value or address. */
@@ -669,14 +580,136 @@ int ED_IsBool (const ExprDesc* Expr);
** be an operand to a compare operation with 0/NULL.
*/
void PrintExprDesc (FILE* F, ExprDesc* Expr);
/* Print an ExprDesc */
/*****************************************************************************/
/* Manipulation */
/*****************************************************************************/
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type);
/* Replace Expr with an absolute const with the given value and type */
ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value);
/* Replace Expr with an constant integer with the given value */
ExprDesc* ED_MakeConstBool (ExprDesc* Expr, long Value);
/* Replace Expr with a constant boolean expression with the given value */
ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr);
/* Finalize the result of LoadExpr to be an rvalue in the primary register */
#if defined(HAVE_INLINE)
INLINE void ED_MarkExprAsLVal (ExprDesc* Expr)
/* Mark the expression as an lvalue.
** HINT: Consider using ED_IndExpr instead of this, unless you know what
** consequence there will be, as there are both a big part in the code
** assuming rvalue = const and a big part assuming rvalue = address.
*/
{
Expr->Flags |= E_RTYPE_LVAL;
}
#else
# define ED_MarkExprAsLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MarkExprAsRVal (ExprDesc* Expr)
/* Mark the expression as an rvalue.
** HINT: Consider using ED_AddrExpr instead of this, unless you know what
** consequence there will be, as there are both a big part in the code
** assuming rvalue = const and a big part assuming rvalue = address.
*/
{
Expr->Flags &= ~E_RTYPE_LVAL;
}
#else
# define ED_MarkExprAsRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
#endif
ExprDesc* ED_AddrExpr (ExprDesc* Expr);
/* Take address of Expr */
ExprDesc* ED_IndExpr (ExprDesc* Expr);
/* Dereference Expr */
#if defined(HAVE_INLINE)
INLINE void ED_RequireTest (ExprDesc* Expr)
/* Mark the expression for a test. */
{
Expr->Flags |= E_NEED_TEST;
}
#else
# define ED_RequireTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_RequireNoTest (ExprDesc* Expr)
/* Mark the expression not for a test. */
{
Expr->Flags &= ~E_NEED_TEST;
}
#else
# define ED_RequireNoTest(Expr) do { (Expr)->Flags &= ~E_NEED_TEST; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_TestDone (ExprDesc* Expr)
/* Mark the expression as tested and condition codes set. */
{
Expr->Flags |= E_CC_SET;
}
#else
# define ED_TestDone(Expr) \
do { (Expr)->Flags |= E_CC_SET; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MarkAsUntested (ExprDesc* Expr)
/* Mark the expression as not tested (condition codes not set). */
{
Expr->Flags &= ~E_CC_SET;
}
#else
# define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0)
#endif
void ED_MarkForUneval (ExprDesc* Expr);
/* Mark the expression as not to be evaluated */
#if defined(HAVE_INLINE)
INLINE void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr)
/* Propagate viral flags from subexpression */
{
Expr->Flags |= SubExpr->Flags & E_MASK_VIRAL;
}
#else
# define ED_PropagateFrom(Expr, SubExpr) (void)((Expr)->Flags |= (SubExpr)->Flags & E_MASK_VIRAL)
#endif
const Type* ReplaceType (ExprDesc* Expr, const Type* NewType);
/* Replace the type of Expr by a copy of Newtype and return the old type string */
/*****************************************************************************/
/* Other Helpers */
/*****************************************************************************/
void PrintExprDesc (FILE* F, ExprDesc* Expr);
/* Print an ExprDesc */
void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End);
/* Set the code range for this expression */
int ED_CodeRangeIsEmpty (const ExprDesc* Expr);
/* Return true if no code was output for this expression */
/* End of exprdesc.h */
#endif

View File

@@ -42,6 +42,7 @@
#include "asmlabel.h"
#include "codegen.h"
#include "error.h"
#include "expr.h"
#include "funcdesc.h"
#include "global.h"
#include "litpool.h"
@@ -613,7 +614,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
/* Could we allocate a register? */
if (Reg < 0) {
/* No register available: Convert parameter to auto */
CvtRegVarToAuto (Param);
SymCvtRegVarToAuto (Param);
} else {
/* Remember the register offset */
Param->V.R.RegOffs = Reg;

View File

@@ -49,6 +49,7 @@ unsigned char DebugInfo = 0; /* Add debug info to the obj */
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
unsigned char DebugOptOutput = 0; /* Output debug stuff */
unsigned RegisterSpace = 6; /* Space available for register vars */
unsigned AllowNewComments = 0; /* Allow new style comments in C89 mode */
/* Stackable options */
IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */

View File

@@ -57,6 +57,7 @@ extern unsigned char DebugInfo; /* Add debug info to the obj */
extern unsigned char PreprocessOnly; /* Just preprocess the input */
extern unsigned char DebugOptOutput; /* Output debug stuff */
extern unsigned RegisterSpace; /* Space available for register vars */
extern unsigned AllowNewComments; /* Allow new style comments in C89 mode */
/* Stackable options */
extern IntStack WritableStrings; /* Literal strings are r/w */

View File

@@ -437,7 +437,7 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
/* Parse initialization of a struct or union. Return the number of data bytes. */
{
SymEntry* Sym;
SymEntry* TagSym;
SymTable* Tab;
StructInitData SI;
int HasCurly = 0;
@@ -452,15 +452,15 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
}
/* Get a pointer to the struct entry from the type */
Sym = GetESUSymEntry (T);
TagSym = GetESUTagSym (T);
/* Get the size of the struct from the symbol table entry */
SI.Size = Sym->V.S.Size;
SI.Size = TagSym->V.S.Size;
/* Check if this struct definition has a field table. If it doesn't, it
** is an incomplete definition.
*/
Tab = Sym->V.S.SymTab;
Tab = TagSym->V.S.SymTab;
if (Tab == 0) {
Error ("Cannot initialize variables with incomplete type");
/* Try error recovery */
@@ -470,7 +470,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
}
/* Get a pointer to the list of symbols */
Sym = Tab->SymHead;
TagSym = Tab->SymHead;
/* Initialize fields */
SI.Offs = 0;
@@ -479,7 +479,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
while (CurTok.Tok != TOK_RCURLY) {
/* Check for excess elements */
if (Sym == 0) {
if (TagSym == 0) {
/* Is there just one trailing comma before a closing curly? */
if (NextTok.Tok == TOK_RCURLY && CurTok.Tok == TOK_COMMA) {
/* Skip comma and exit scope */
@@ -495,7 +495,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
}
/* Check for special members that don't consume the initializer */
if ((Sym->Flags & SC_ALIAS) == SC_ALIAS) {
if ((TagSym->Flags & SC_ALIAS) == SC_ALIAS) {
/* Just skip */
goto NextMember;
}
@@ -503,13 +503,13 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
/* This may be an anonymous bit-field, in which case it doesn't
** have an initializer.
*/
if (SymIsBitField (Sym) && (IsAnonName (Sym->Name))) {
if (SymIsBitField (TagSym) && (IsAnonName (TagSym->Name))) {
/* Account for the data and output it if we have at least a full
** byte. We may have more if there was storage unit overlap, for
** example two consecutive 7 bit fields. Those would be packed
** into 2 bytes.
*/
SI.ValBits += Sym->Type->A.B.Width;
SI.ValBits += TagSym->Type->A.B.Width;
CHECK (SI.ValBits <= CHAR_BIT * sizeof(SI.BitVal));
/* TODO: Generalize this so any type can be used. */
CHECK (SI.ValBits <= LONG_BITS);
@@ -526,7 +526,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
SkipComma = 0;
}
if (SymIsBitField (Sym)) {
if (SymIsBitField (TagSym)) {
/* Parse initialization of one field. Bit-fields need a special
** handling.
@@ -537,14 +537,14 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
unsigned Shift;
/* Calculate the bitmask from the bit-field data */
unsigned long Mask = shl_l (1UL, Sym->Type->A.B.Width) - 1UL;
unsigned long Mask = shl_l (1UL, TagSym->Type->A.B.Width) - 1UL;
/* Safety ... */
CHECK (Sym->V.Offs * CHAR_BITS + Sym->Type->A.B.Offs ==
CHECK (TagSym->V.Offs * CHAR_BITS + TagSym->Type->A.B.Offs ==
SI.Offs * CHAR_BITS + SI.ValBits);
/* Read the data, check for a constant integer, do a range check */
Field = ParseScalarInitInternal (IntPromotion (Sym->Type));
Field = ParseScalarInitInternal (IntPromotion (TagSym->Type));
if (!ED_IsConstAbsInt (&Field)) {
Error ("Constant initializer expected");
ED_MakeConstAbsInt (&Field, 1);
@@ -554,19 +554,19 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
** any useful bits.
*/
Val = (unsigned long) Field.IVal & Mask;
if (IsSignUnsigned (Sym->Type)) {
if (IsSignUnsigned (TagSym->Type)) {
if (Field.IVal < 0 || (unsigned long) Field.IVal != Val) {
Warning (IsSignUnsigned (Field.Type) ?
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
" changes value from %lu to %lu" :
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
" changes value from %ld to %lu",
GetFullTypeName (Field.Type), GetFullTypeName (Sym->Type),
Sym->Type->A.B.Width, Field.IVal, Val);
GetFullTypeName (Field.Type), GetFullTypeName (TagSym->Type),
TagSym->Type->A.B.Width, Field.IVal, Val);
}
} else {
/* Sign extend back to full width of host long. */
unsigned ShiftBits = sizeof (long) * CHAR_BIT - Sym->Type->A.B.Width;
unsigned ShiftBits = sizeof (long) * CHAR_BIT - TagSym->Type->A.B.Width;
long RestoredVal = asr_l (asl_l (Val, ShiftBits), ShiftBits);
if (Field.IVal != RestoredVal) {
Warning (IsSignUnsigned (Field.Type) ?
@@ -574,17 +574,17 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
" changes value from %lu to %ld" :
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
" changes value from %ld to %ld",
GetFullTypeName (Field.Type), GetFullTypeName (Sym->Type),
Sym->Type->A.B.Width, Field.IVal, RestoredVal);
GetFullTypeName (Field.Type), GetFullTypeName (TagSym->Type),
TagSym->Type->A.B.Width, Field.IVal, RestoredVal);
}
}
/* Add the value to the currently stored bit-field value */
Shift = (Sym->V.Offs - SI.Offs) * CHAR_BITS + Sym->Type->A.B.Offs;
Shift = (TagSym->V.Offs - SI.Offs) * CHAR_BITS + TagSym->Type->A.B.Offs;
SI.BitVal |= (Val << Shift);
/* Account for the data and output any full bytes we have. */
SI.ValBits += Sym->Type->A.B.Width;
SI.ValBits += TagSym->Type->A.B.Width;
/* Make sure unsigned is big enough to hold the value, 32 bits.
** This cannot be more than 32 bits because a 16-bit or 32-bit
** bit-field will always be byte-aligned with padding before it
@@ -602,14 +602,14 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
/* Standard member. We should never have stuff from a
** bit-field left because an anonymous member was added
** for padding by ParseStructDecl.
** for padding by ParseStructSpec.
*/
CHECK (SI.ValBits == 0);
/* Flexible array members may only be initialized if they are
** the last field (or part of the last struct field).
*/
SI.Offs += ParseInitInternal (Sym->Type, Braces, AllowFlexibleMembers && Sym->NextSym == 0);
SI.Offs += ParseInitInternal (TagSym->Type, Braces, AllowFlexibleMembers && TagSym->NextSym == 0);
}
/* More initializers? */
@@ -624,10 +624,10 @@ NextMember:
/* Next member. For unions, only the first one can be initialized */
if (IsTypeUnion (T)) {
/* Union */
Sym = 0;
TagSym = 0;
} else {
/* Struct */
Sym = Sym->NextSym;
TagSym = TagSym->NextSym;
}
}

View File

@@ -67,6 +67,9 @@
/* The current input line */
StrBuf* Line;
/* The input line to reuse as the next line */
static StrBuf* CurReusedLine;
/* Current and next input character */
char CurC = '\0';
char NextC = '\0';
@@ -103,8 +106,8 @@ static Collection IFiles = STATIC_COLLECTION_INITIALIZER;
/* List of all active files */
static Collection AFiles = STATIC_COLLECTION_INITIALIZER;
/* Input stack used when preprocessing. */
static Collection InputStack = STATIC_COLLECTION_INITIALIZER;
/* Input stack used when preprocessing */
static Collection* CurrentInputStack;
/* Counter for the __COUNTER__ macro */
static unsigned MainFileCounter;
@@ -394,34 +397,19 @@ static void GetInputChar (void)
** are read by this function.
*/
{
/* Drop all pushed fragments that don't have data left */
while (SB_GetIndex (Line) >= SB_GetLen (Line)) {
/* Cannot read more from this line, check next line on stack if any */
if (CollCount (&InputStack) == 0) {
/* This is THE line */
break;
}
FreeStrBuf (Line);
Line = CollPop (&InputStack);
/* Get the next-next character from the line */
if (SB_GetIndex (Line) + 1 < SB_GetLen (Line)) {
/* CurC and NextC come from this fragment */
CurC = SB_AtUnchecked (Line, SB_GetIndex (Line));
NextC = SB_AtUnchecked (Line, SB_GetIndex (Line) + 1);
} else {
/* NextC is '\0' by default */
NextC = '\0';
/* Get CurC from the line */
CurC = SB_LookAt (Line, SB_GetIndex (Line));
}
/* Now get the next characters from the line */
if (SB_GetIndex (Line) >= SB_GetLen (Line)) {
CurC = NextC = '\0';
} else {
CurC = SB_AtUnchecked (Line, SB_GetIndex (Line));
if (SB_GetIndex (Line) + 1 < SB_GetLen (Line)) {
/* NextC comes from this fragment */
NextC = SB_AtUnchecked (Line, SB_GetIndex (Line) + 1);
} else {
/* NextC comes from next fragment */
if (CollCount (&InputStack) > 0) {
NextC = ' ';
} else {
NextC = '\0';
}
}
}
}
@@ -441,17 +429,41 @@ void NextChar (void)
Collection* UseInputStack (Collection* InputStack)
/* Use the provided input stack for incoming input. Return the previously used
** InputStack.
*/
{
Collection* OldInputStack = CurrentInputStack;
CurrentInputStack = InputStack;
return OldInputStack;
}
void PushLine (StrBuf* L)
/* Save the current input line and use a new one */
{
PRECONDITION (CurrentInputStack != 0);
CollAppend (CurrentInputStack, Line);
Line = L;
GetInputChar ();
}
void ReuseInputLine (void)
/* Save and reuse the current line as the next line */
{
CurReusedLine = Line;
}
void ClearLine (void)
/* Clear the current input line */
{
unsigned I;
/* Remove all pushed fragments from the input stack */
for (I = 0; I < CollCount (&InputStack); ++I) {
FreeStrBuf (CollAtUnchecked (&InputStack, I));
}
CollDeleteAll (&InputStack);
/* Clear the contents of Line */
SB_Clear (Line);
CurC = '\0';
@@ -482,12 +494,47 @@ int NextLine (void)
int C;
AFile* Input;
/* Clear the current line */
ClearLine ();
SB_Clear (Line);
/* Overwrite the next input line with the pushed line if there is one */
if (CurReusedLine != 0) {
/* Use data move to resolve the issue that Line may be impersistent */
if (Line != CurReusedLine) {
SB_Move (Line, CurReusedLine);
}
/* Continue with this Line */
InitLine (Line);
CurReusedLine = 0;
/* Must have an input file when called */
if (CollCount(&AFiles) == 0) {
return 1;
}
/* If there are pushed input lines, read from them */
if (CurrentInputStack != 0 && CollCount (CurrentInputStack) > 0) {
/* Drop all pushed fragments that have no data left until one can be
** used as input.
*/
do {
/* Use data move to resolve the issue that Line may be impersistent */
if (Line != CollLast (CurrentInputStack)) {
SB_Move (Line, CollPop (CurrentInputStack));
} else {
CollPop (CurrentInputStack);
}
} while (CollCount (CurrentInputStack) > 0 &&
SB_GetIndex (Line) >= SB_GetLen (Line));
if (SB_GetIndex (Line) < SB_GetLen (Line)) {
InitLine (Line);
/* Successive */
return 1;
}
}
/* Otherwise, clear the current line */
ClearLine ();
/* Must have an input file when going on */
if (CollCount (&AFiles) == 0) {
return 0;
}
@@ -531,15 +578,16 @@ int NextLine (void)
SB_Drop (Line, 1);
}
/* If we don't have a line continuation character at the end,
** we're done with this line. Otherwise replace the character
** by a newline and continue reading.
/* If we don't have a line continuation character at the end, we
** are done with this line. Otherwise just skip the character and
** continue reading.
*/
if (SB_LookAtLast (Line) == '\\') {
Line->Buf[Line->Len-1] = '\n';
} else {
if (SB_LookAtLast (Line) != '\\') {
Input->MissingNL = 0;
break;
} else {
SB_Drop (Line, 1);
ContinueLine ();
}
} else if (C != '\0') { /* Ignore embedded NULs */
@@ -605,7 +653,7 @@ const char* GetInputFile (const struct IFile* IF)
const char* GetCurrentFile (void)
const char* GetCurrentFilename (void)
/* Return the name of the current input file */
{
unsigned AFileCount = CollCount (&AFiles);
@@ -620,7 +668,7 @@ const char* GetCurrentFile (void)
unsigned GetCurrentLine (void)
unsigned GetCurrentLineNum (void)
/* Return the line number in the current input file */
{
unsigned AFileCount = CollCount (&AFiles);
@@ -635,7 +683,7 @@ unsigned GetCurrentLine (void)
void SetCurrentLine (unsigned LineNum)
void SetCurrentLineNum (unsigned LineNum)
/* Set the line number in the current input file */
{
unsigned AFileCount = CollCount (&AFiles);

View File

@@ -41,6 +41,7 @@
#include <stdio.h>
/* common */
#include "coll.h"
#include "strbuf.h"
@@ -95,6 +96,17 @@ void NextChar (void);
** are read by this function.
*/
Collection* UseInputStack (Collection* InputStack);
/* Use the provided input stack for incoming input. Return the previously used
** InputStack.
*/
void PushLine (StrBuf* L);
/* Save the current input line and use a new one */
void ReuseInputLine (void);
/* Save and reuse the current line as the next line */
void ClearLine (void);
/* Clear the current input line */
@@ -116,13 +128,13 @@ int PreprocessNextLine (void);
const char* GetInputFile (const struct IFile* IF);
/* Return a filename from an IFile struct */
const char* GetCurrentFile (void);
const char* GetCurrentFilename (void);
/* Return the name of the current input file */
unsigned GetCurrentLine (void);
unsigned GetCurrentLineNum (void);
/* Return the line number in the current input file */
void SetCurrentLine (unsigned LineNum);
void SetCurrentLineNum (unsigned LineNum);
/* Set the line number in the current input file */
void SetCurrentFilename (const char* Name);

View File

@@ -36,6 +36,7 @@
/* cc65 */
#include "codegen.h"
#include "error.h"
#include "expr.h"
#include "exprdesc.h"
#include "global.h"
#include "loadexpr.h"
@@ -92,7 +93,6 @@ static void LoadAddress (unsigned Flags, ExprDesc* Expr)
g_leasp (Expr->IVal);
break;
case E_LOC_PRIMARY:
case E_LOC_EXPR:
if (Expr->IVal != 0) {
/* We have an expression in the primary plus a constant

View File

@@ -97,8 +97,8 @@ static void AllocStorage (unsigned DataLabel, void (*UseSeg) (), unsigned Size)
static void ParseRegisterDecl (Declaration* Decl, int Reg)
/* Parse the declaration of a register variable. Reg is the offset of the
static void ParseRegisterDecl (Declarator* Decl, int Reg)
/* Parse the declarator of a register variable. Reg is the offset of the
** variable in the register bank.
*/
{
@@ -186,8 +186,8 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg)
static void ParseAutoDecl (Declaration* Decl)
/* Parse the declaration of an auto variable. */
static void ParseAutoDecl (Declarator* Decl)
/* Parse the declarator of an auto variable. */
{
unsigned Flags;
SymEntry* Sym;
@@ -287,7 +287,7 @@ static void ParseAutoDecl (Declaration* Decl)
** We abuse the Collection somewhat by using it to store line
** numbers.
*/
CollReplace (&CurrentFunc->LocalsBlockStack, (void *)(size_t)GetCurrentLine (),
CollReplace (&CurrentFunc->LocalsBlockStack, (void *)(size_t)GetCurrentLineNum (),
CollCount (&CurrentFunc->LocalsBlockStack) - 1);
} else {
@@ -382,8 +382,8 @@ static void ParseAutoDecl (Declaration* Decl)
static void ParseStaticDecl (Declaration* Decl)
/* Parse the declaration of a static variable. */
static void ParseStaticDecl (Declarator* Decl)
/* Parse the declarator of a static variable. */
{
unsigned Size;
@@ -441,12 +441,12 @@ static void ParseStaticDecl (Declaration* Decl)
static void ParseOneDecl (const DeclSpec* Spec)
/* Parse one variable declaration */
/* Parse one variable declarator. */
{
Declaration Decl; /* Declaration data structure */
Declarator Decl; /* Declarator data structure */
/* Read the declaration */
/* Read the declarator */
ParseDecl (Spec, &Decl, DM_NEED_IDENT);
/* Check if there are any non-extern storage classes set for function
@@ -465,8 +465,8 @@ static void ParseOneDecl (const DeclSpec* Spec)
/* The default storage class could be wrong. Just clear them */
Decl.StorageClass &= ~SC_STORAGEMASK;
/* This is always a declaration */
Decl.StorageClass |= SC_DECL;
/* This is always an extern declaration */
Decl.StorageClass |= SC_DECL | SC_EXTERN;
}
/* If we don't have a name, this was flagged as an error earlier.
@@ -524,7 +524,9 @@ static void ParseOneDecl (const DeclSpec* Spec)
if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN ||
(Decl.StorageClass & SC_FUNC) == SC_FUNC) {
/* Add the global symbol to the local symbol table */
/* Add the global symbol to both of the global and local symbol
** tables.
*/
AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
} else {
/* Add the local symbol to the local symbol table */
@@ -566,7 +568,7 @@ void DeclareLocals (void)
continue;
}
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_AUTO);
if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */
(Spec.Flags & DS_DEF_TYPE) != 0 && /* No type given */
GetQualifier (Spec.Type) == T_QUAL_NONE) { /* No type qualifier */

View File

@@ -74,19 +74,17 @@ Macro* NewMacro (const char* Name)
*/
{
/* Get the length of the macro name */
unsigned Len = strlen(Name);
unsigned Len = strlen (Name);
/* Allocate the structure */
Macro* M = (Macro*) xmalloc (sizeof(Macro) + Len);
/* Initialize the data */
M->Next = 0;
M->Expanding = 0;
M->ArgCount = -1; /* Flag: Not a function like macro */
M->MaxArgs = 0;
InitCollection (&M->FormalArgs);
M->Next = 0;
M->ParamCount = -1; /* Flag: Not a function-like macro */
InitCollection (&M->Params);
SB_Init (&M->Replacement);
M->Variadic = 0;
M->Variadic = 0;
memcpy (M->Name, Name, Len+1);
/* Return the new macro */
@@ -102,10 +100,10 @@ void FreeMacro (Macro* M)
{
unsigned I;
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
xfree (CollAtUnchecked (&M->FormalArgs, I));
for (I = 0; I < CollCount (&M->Params); ++I) {
xfree (CollAtUnchecked (&M->Params, I));
}
DoneCollection (&M->FormalArgs);
DoneCollection (&M->Params);
SB_Done (&M->Replacement);
xfree (M);
}
@@ -121,12 +119,12 @@ Macro* CloneMacro (const Macro* M)
Macro* New = NewMacro (M->Name);
unsigned I;
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
/* Copy the argument */
const char* Arg = CollAtUnchecked (&M->FormalArgs, I);
CollAppend (&New->FormalArgs, xstrdup (Arg));
for (I = 0; I < CollCount (&M->Params); ++I) {
/* Copy the parameter */
const char* Param = CollAtUnchecked (&M->Params, I);
CollAppend (&New->Params, xstrdup (Param));
}
New->ArgCount = M->ArgCount;
New->ParamCount = M->ParamCount;
New->Variadic = M->Variadic;
SB_Copy (&New->Replacement, &M->Replacement);
@@ -265,14 +263,14 @@ Macro* FindMacro (const char* Name)
int FindMacroArg (Macro* M, const char* Arg)
/* Search for a formal macro argument. If found, return the index of the
** argument. If the argument was not found, return -1.
int FindMacroParam (const Macro* M, const char* Param)
/* Search for a macro parameter. If found, return the index of the parameter.
** If the parameter was not found, return -1.
*/
{
unsigned I;
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
for (I = 0; I < CollCount (&M->Params); ++I) {
if (strcmp (CollAtUnchecked (&M->Params, I), Param) == 0) {
/* Found */
return I;
}
@@ -284,25 +282,25 @@ int FindMacroArg (Macro* M, const char* Arg)
void AddMacroArg (Macro* M, const char* Arg)
/* Add a formal macro argument. */
void AddMacroParam (Macro* M, const char* Param)
/* Add a macro parameter. */
{
/* Check if we have a duplicate macro argument, but add it anyway.
** Beware: Don't use FindMacroArg here, since the actual argument array
/* Check if we have a duplicate macro parameter, but add it anyway.
** Beware: Don't use FindMacroParam here, since the actual argument array
** may not be initialized.
*/
unsigned I;
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
for (I = 0; I < CollCount (&M->Params); ++I) {
if (strcmp (CollAtUnchecked (&M->Params, I), Param) == 0) {
/* Found */
PPError ("Duplicate macro parameter: '%s'", Arg);
PPError ("Duplicate macro parameter: '%s'", Param);
break;
}
}
/* Add the new argument */
CollAppend (&M->FormalArgs, xstrdup (Arg));
++M->ArgCount;
/* Add the new parameter */
CollAppend (&M->Params, xstrdup (Param));
++M->ParamCount;
}
@@ -313,14 +311,14 @@ int MacroCmp (const Macro* M1, const Macro* M2)
int I;
/* Argument count must be identical */
if (M1->ArgCount != M2->ArgCount) {
if (M1->ParamCount != M2->ParamCount) {
return 1;
}
/* Compare the arguments */
for (I = 0; I < M1->ArgCount; ++I) {
if (strcmp (CollConstAt (&M1->FormalArgs, I),
CollConstAt (&M2->FormalArgs, I)) != 0) {
/* Compare the parameters */
for (I = 0; I < M1->ParamCount; ++I) {
if (strcmp (CollConstAt (&M1->Params, I),
CollConstAt (&M2->Params, I)) != 0) {
return 1;
}
}

View File

@@ -55,10 +55,8 @@
typedef struct Macro Macro;
struct Macro {
Macro* Next; /* Next macro with same hash value */
int Expanding; /* Are we currently expanding this macro? */
int ArgCount; /* Number of parameters, -1 = no parens */
unsigned MaxArgs; /* Size of formal argument list */
Collection FormalArgs; /* Formal argument list (char*) */
int ParamCount; /* Number of parameters, -1 = no parens */
Collection Params; /* Parameter list (char*) */
StrBuf Replacement; /* Replacement text */
unsigned char Variadic; /* C99 variadic macro */
char Name[1]; /* Name, dynamically allocated */
@@ -120,13 +118,13 @@ INLINE int IsMacro (const char* Name)
# define IsMacro(Name) (FindMacro (Name) != 0)
#endif
int FindMacroArg (Macro* M, const char* Arg);
/* Search for a formal macro argument. If found, return the index of the
** argument. If the argument was not found, return -1.
int FindMacroParam (const Macro* M, const char* Param);
/* Search for a macro parameter. If found, return the index of the parameter.
** If the parameter was not found, return -1.
*/
void AddMacroArg (Macro* M, const char* Arg);
/* Add a formal macro argument. */
void AddMacroParam (Macro* M, const char* Param);
/* Add a macro parameter. */
int MacroCmp (const Macro* M1, const Macro* M2);
/* Compare two macros and return zero if both are identical. */

View File

@@ -305,97 +305,60 @@ static void PPhie_internal (const token_t* Ops, /* List of generators */
if (PPEvaluationEnabled && !PPEvaluationFailed) {
/* Evaluate the result for operands */
unsigned long Val1 = Expr->IVal;
unsigned long Val2 = Rhs.IVal;
/* If either side is unsigned, the result is unsigned */
Expr->Flags |= Rhs.Flags & PPEXPR_UNSIGNED;
/* Handle the op differently for signed and unsigned integers */
if ((Expr->Flags & PPEXPR_UNSIGNED) == 0) {
/* Evaluate the result for signed operands */
signed long Val1 = Expr->IVal;
signed long Val2 = Rhs.IVal;
switch (Tok) {
case TOK_OR:
Expr->IVal = (Val1 | Val2);
break;
case TOK_XOR:
Expr->IVal = (Val1 ^ Val2);
break;
case TOK_AND:
Expr->IVal = (Val1 & Val2);
break;
case TOK_PLUS:
Expr->IVal = (Val1 + Val2);
break;
case TOK_MINUS:
Expr->IVal = (Val1 - Val2);
break;
case TOK_MUL:
Expr->IVal = (Val1 * Val2);
break;
case TOK_DIV:
if (Val2 == 0) {
PPError ("Division by zero");
Expr->IVal = 0;
switch (Tok) {
case TOK_OR:
Expr->IVal = (Val1 | Val2);
break;
case TOK_XOR:
Expr->IVal = (Val1 ^ Val2);
break;
case TOK_AND:
Expr->IVal = (Val1 & Val2);
break;
case TOK_PLUS:
Expr->IVal = (Val1 + Val2);
break;
case TOK_MINUS:
Expr->IVal = (Val1 - Val2);
break;
case TOK_MUL:
Expr->IVal = (Val1 * Val2);
break;
case TOK_DIV:
if (Val2 == 0) {
PPError ("Division by zero");
Expr->IVal = 0;
} else {
/* Handle signed and unsigned operands differently */
if ((Expr->Flags & PPEXPR_UNSIGNED) == 0) {
Expr->IVal = ((long)Val1 / (long)Val2);
} else {
Expr->IVal = (Val1 / Val2);
}
break;
case TOK_MOD:
if (Val2 == 0) {
PPError ("Modulo operation with zero");
Expr->IVal = 0;
}
break;
case TOK_MOD:
if (Val2 == 0) {
PPError ("Modulo operation with zero");
Expr->IVal = 0;
} else {
/* Handle signed and unsigned operands differently */
if ((Expr->Flags & PPEXPR_UNSIGNED) == 0) {
Expr->IVal = ((long)Val1 % (long)Val2);
} else {
Expr->IVal = (Val1 % Val2);
}
break;
default:
Internal ("PPhie_internal: got token 0x%X\n", Tok);
}
} else {
/* Evaluate the result for unsigned operands */
unsigned long Val1 = Expr->IVal;
unsigned long Val2 = Rhs.IVal;
switch (Tok) {
case TOK_OR:
Expr->IVal = (Val1 | Val2);
break;
case TOK_XOR:
Expr->IVal = (Val1 ^ Val2);
break;
case TOK_AND:
Expr->IVal = (Val1 & Val2);
break;
case TOK_PLUS:
Expr->IVal = (Val1 + Val2);
break;
case TOK_MINUS:
Expr->IVal = (Val1 - Val2);
break;
case TOK_MUL:
Expr->IVal = (Val1 * Val2);
break;
case TOK_DIV:
if (Val2 == 0) {
PPError ("Division by zero");
Expr->IVal = 0;
} else {
Expr->IVal = (Val1 / Val2);
}
break;
case TOK_MOD:
if (Val2 == 0) {
PPError ("Modulo operation with zero");
Expr->IVal = 0;
} else {
Expr->IVal = (Val1 % Val2);
}
break;
default:
Internal ("PPhie_internal: got token 0x%X\n", Tok);
}
}
break;
default:
Internal ("PPhie_internal: got token 0x%X\n", Tok);
}
}
}
@@ -519,12 +482,21 @@ static void PPhie7 (PPExpr* Expr)
/* Evaluate */
if (PPEvaluationEnabled && !PPEvaluationFailed) {
/* To shift by a negative value is equivalent to shift to the
** opposite direction.
*/
if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0 && Rhs.IVal > (long)LONG_BITS) {
/* For now we use 32-bit integer types for PP integer constants */
if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0) {
if ((unsigned long)Rhs.IVal > LONG_BITS) {
Rhs.IVal = (long)LONG_BITS;
}
} else if (Rhs.IVal > (long)LONG_BITS) {
Rhs.IVal = (long)LONG_BITS;
} else if (Rhs.IVal < -(long)LONG_BITS) {
Rhs.IVal = -(long)LONG_BITS;
}
/* Positive count for left-shift and negative for right-shift. So
** to shift by a count is equivalent to shift to the opposite
** direction by the negated count.
*/
if (Op == TOK_SHR) {
Rhs.IVal = -Rhs.IVal;
}
@@ -532,27 +504,26 @@ static void PPhie7 (PPExpr* Expr)
/* Evaluate the result */
if ((Expr->Flags & PPEXPR_UNSIGNED) != 0) {
if (Rhs.IVal >= (long)LONG_BITS) {
/* For now we use (unsigned) long types for integer constants */
PPWarning ("Integer overflow in preprocessor expression");
Expr->IVal = 0;
} else if (Rhs.IVal > 0) {
Expr->IVal <<= Rhs.IVal;
} else if (Rhs.IVal < -(long)LONG_BITS) {
} else if (Rhs.IVal <= -(long)LONG_BITS) {
Expr->IVal = 0;
} else if (Rhs.IVal < 0) {
Expr->IVal = (unsigned long)Expr->IVal >> -Rhs.IVal;
}
} else {
/* -1 for sign bit */
if (Rhs.IVal >= (long)(LONG_BITS - 1)) {
/* For now we use (unsigned) long types for integer constants */
PPWarning ("Integer overflow in preprocessor expression");
Expr->IVal = 0;
} else if (Rhs.IVal > 0) {
Expr->IVal <<= Rhs.IVal;
} else if (Rhs.IVal < -(long)LONG_BITS) {
Expr->IVal = -1;
} else if (Rhs.IVal <= -(long)LONG_BITS) {
Expr->IVal = Expr->IVal >= 0 ? 0 : -1;
} else if (Rhs.IVal < 0) {
Expr->IVal >>= Expr->IVal >> -Rhs.IVal;
Expr->IVal = (long)Expr->IVal >> -Rhs.IVal;
}
}
}
@@ -752,7 +723,7 @@ static void PPhieQuest (PPExpr* Expr)
/* Parse third expression */
PPExprInit (&Expr3);
PPhie1 (&Expr3);
PPhieQuest (&Expr3);
/* Set the result */
Expr->IVal = Expr->IVal ? Expr2.IVal != 0 : Expr3.IVal != 0;

View File

@@ -784,7 +784,7 @@ static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High)
static void MakeMessage (const char* Message)
{
fprintf (stderr, "%s:%u: Note: %s\n", GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Message);
Note ("%s", Message);
}

File diff suppressed because it is too large Load Diff

View File

@@ -36,17 +36,7 @@
#ifndef PREPROC_H
#define PREPROC_H
/*****************************************************************************/
/* Forwards */
/*****************************************************************************/
typedef struct Macro Macro;
#include "macrotab.h"
/*****************************************************************************/
/* Data */
@@ -78,6 +68,9 @@ void Preprocess (void);
void SetPPIfStack (PPIfStack* Stack);
/* Specify which PP #if stack to use */
void ContinueLine (void);
/* Continue the current line ended with a '\\' */
void PreprocessBegin (void);
/* Initialize preprocessor with current file */

View File

@@ -235,10 +235,20 @@ void SymName (char* S)
int IsWideQuoted (char First, char Second)
/* Return 1 if the two successive characters indicate a wide string literal or
** a wide char constant, otherwise return 0.
*/
{
return First == 'L' && IsQuote(Second);
}
int IsSym (char* S)
/* If a symbol follows, read it and return 1, otherwise return 0 */
{
if (IsIdent (CurC)) {
if (IsIdent (CurC) && !IsWideQuoted (CurC, NextC)) {
SymName (S);
return 1;
} else {
@@ -633,7 +643,7 @@ static void NumericConst (void)
if (IVal <= 0xFFFF &&
(Types & IT_UINT) == 0 &&
(WarnTypes & IT_LONG) != 0) {
Warning ("Integer constant is long");
Warning ("Integer constant implies signed long");
}
}
if (IVal > 0xFFFF) {
@@ -650,7 +660,7 @@ static void NumericConst (void)
** a preceding unary op or when it is used in constant calculation.
*/
if (WarnTypes & IT_ULONG) {
Warning ("Integer constant is unsigned long");
Warning ("Integer constant implies unsigned long");
}
}

View File

@@ -282,6 +282,11 @@ void SymName (char* S);
** least of size MAX_IDENTLEN+1.
*/
int IsWideQuoted (char First, char Second);
/* Return 1 if the two successive characters indicate a wide string literal or
** a wide char constant, otherwise return 0.
*/
int IsSym (char* S);
/* If a symbol follows, read it and return 1, otherwise return 0 */

View File

@@ -139,20 +139,34 @@ void ShiftExpr (struct ExprDesc* Expr)
/* Remove the code that pushes the rhs onto the stack. */
RemoveCode (&Mark2);
/* If the shift count is greater or equal than the bit count of
** the operand, the behaviour is undefined according to the
** standard.
/* If the shift count is greater than or equal to the width of the
** promoted left operand, the behaviour is undefined according to
** the standard.
*/
if (Expr2.IVal < 0) {
if (!ED_IsUneval (Expr)) {
if (Expr2.IVal < 0) {
Warning ("Negative shift count %ld treated as %u for %s",
Expr2.IVal,
(unsigned)Expr2.IVal & (ExprBits - 1),
GetBasicTypeName (ResultType));
} else if (Expr2.IVal >= (long) ExprBits) {
Warning ("Shift count %ld >= width of %s treated as %u",
Expr2.IVal,
GetBasicTypeName (ResultType),
(unsigned)Expr2.IVal & (ExprBits - 1));
}
}
Warning ("Shift count '%ld' is negative", Expr2.IVal);
Expr2.IVal &= ExprBits - 1;
} else if (Expr2.IVal >= (long) ExprBits) {
Warning ("Shift count '%ld' >= width of type", Expr2.IVal);
Expr2.IVal &= ExprBits - 1;
/* Here we simply "wrap" the shift count around the width */
Expr2.IVal &= ExprBits - 1;
/* Additional check for bit-fields */
if (IsTypeBitField (Expr->Type) &&
Tok == TOK_SHR &&
Expr2.IVal >= (long) Expr->Type->A.B.Width) {
if (!ED_IsUneval (Expr)) {
Warning ("Right-shift count %ld >= width of bit-field", Expr2.IVal);
}
}
/* If the shift count is zero, nothing happens. If the left hand
@@ -173,7 +187,7 @@ void ShiftExpr (struct ExprDesc* Expr)
}
/* Limit the calculated value to the range of its type */
LimitExprValue (Expr);
LimitExprValue (Expr, 1);
}
/* Result is already got, remove the generated code */

View File

@@ -40,6 +40,7 @@
/* cc65 */
#include "anonname.h"
#include "asmlabel.h"
#include "declare.h"
#include "error.h"
#include "symentry.h"
@@ -65,13 +66,12 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
E->NextHash = 0;
E->PrevSym = 0;
E->NextSym = 0;
E->Link = 0;
E->Owner = 0;
E->Flags = Flags;
E->Type = 0;
E->Attr = 0;
E->AsmName = 0;
E->V.BssName = 0;
memset (&E->V, 0, sizeof (E->V));
memcpy (E->Name, Name, Len+1);
/* Return the new entry */
@@ -230,8 +230,8 @@ const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType)
void SymUseAttr (SymEntry* Sym, struct Declaration* D)
/* Use the attributes from the declaration for this symbol */
void SymUseAttr (SymEntry* Sym, struct Declarator* D)
/* Use the attributes from the declarator for this symbol */
{
/* We cannot specify attributes twice */
if ((Sym->Flags & SC_HAVEATTR) != 0) {
@@ -250,7 +250,9 @@ void SymUseAttr (SymEntry* Sym, struct Declaration* D)
void SymSetAsmName (SymEntry* Sym)
/* Set the assembler name for an external symbol from the name of the symbol */
/* Set the assembler name for an external symbol from the name of the symbol.
** The symbol must have no assembler name set yet.
*/
{
unsigned Len;
@@ -266,7 +268,7 @@ void SymSetAsmName (SymEntry* Sym)
void CvtRegVarToAuto (SymEntry* Sym)
void SymCvtRegVarToAuto (SymEntry* Sym)
/* Convert a register variable to an auto variable */
{
/* Change the storage class */
@@ -278,59 +280,26 @@ void CvtRegVarToAuto (SymEntry* Sym)
SymEntry* GetSymType (const Type* T)
/* Get the symbol entry of the enum/struct/union type
** Return 0 if it is not an enum/struct/union.
*/
{
if ((IsClassStruct (T) || IsTypeEnum (T))) {
return T->A.S;
}
return 0;
}
const char* GetSymTypeName (const Type* T)
/* Return a name string of the type or the symbol name if it is an ESU type.
** Note: This may use a static buffer that could be overwritten by other calls.
*/
{
static char TypeName [IDENTSIZE + 16];
SymEntry* Sym;
Sym = GetSymType (T);
if (Sym == 0) {
return GetBasicTypeName (T);
}
sprintf (TypeName, "%s %s", GetBasicTypeName (T),
Sym->Name[0] != '\0' ? Sym->Name : "<unknown>");
return TypeName;
}
void ChangeSymType (SymEntry* Entry, const Type* T)
void SymChangeType (SymEntry* Sym, const Type* T)
/* Change the type of the given symbol */
{
TypeFree (Entry->Type);
Entry->Type = TypeDup (T);
TypeFree (Sym->Type);
Sym->Type = TypeDup (T);
}
void ChangeAsmName (SymEntry* Entry, const char* NewAsmName)
void SymChangeAsmName (SymEntry* Sym, const char* NewAsmName)
/* Change the assembler name of the symbol */
{
xfree (Entry->AsmName);
Entry->AsmName = xstrdup (NewAsmName);
xfree (Sym->AsmName);
Sym->AsmName = xstrdup (NewAsmName);
}
int HasAnonName (const SymEntry* Entry)
int SymHasAnonName (const SymEntry* Sym)
/* Return true if the symbol entry has an anonymous name */
{
return IsAnonName (Entry->Name);
return IsAnonName (Sym->Name);
}

View File

@@ -105,8 +105,8 @@ struct CodeEntry;
#define SC_SPADJUSTMENT 0x400000U
#define SC_GOTO_IND 0x800000U /* Indirect goto */
#define SC_ALIAS 0x01000000U /* Alias of anonymous field */
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious */
#define SC_ALIAS 0x01000000U /* Alias of global or anonymous field */
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious (for error recovery) */
#define SC_HAVEFAM 0x04000000U /* Type has a Flexible Array Member */
@@ -128,7 +128,6 @@ struct SymEntry {
SymEntry* NextHash; /* Next entry in hash list */
SymEntry* PrevSym; /* Previous symbol in dl list */
SymEntry* NextSym; /* Next symbol double linked list */
SymEntry* Link; /* General purpose single linked list */
struct SymTable* Owner; /* Symbol table the symbol is in */
unsigned Flags; /* Symbol flags */
Type* Type; /* Symbol type */
@@ -138,27 +137,9 @@ struct SymEntry {
/* Data that differs for the different symbol types */
union {
/* Offset for locals or struct members */
/* Offset for locals */
int Offs;
/* Data for anonymous struct or union members */
struct {
int Offs; /* Byte offset into struct */
unsigned ANumber; /* Numeric ID */
SymEntry* Field; /* The real field aliased */
} A;
/* Label name for static symbols */
struct {
unsigned Label;
Collection *DefsOrRefs;
struct CodeEntry *IndJumpFrom;
} L;
/* Value of SP adjustment needed after forward 'goto' */
unsigned short SPAdjustment;
/* Register bank offset and offset of the saved copy on stack for
** register variables.
*/
@@ -167,32 +148,50 @@ struct SymEntry {
int SaveOffs;
} R;
/* Value for constants (including enums) */
/* Segment name for tentantive global definitions */
const char* BssName;
/* Value for integer constants (including enumerators) */
long ConstVal;
/* Data for structs/unions */
struct {
struct SymTable* SymTab; /* Member symbol table */
unsigned Size; /* Size of the union/struct */
unsigned ACount; /* Count of anonymous fields */
} S;
/* Data for enums */
struct {
struct SymTable* SymTab; /* Member symbol table */
const Type* Type; /* Underlying type */
} E;
/* Data for functions */
struct {
struct Segments* Seg; /* Segments for this function */
struct LiteralPool* LitPool; /* Literal pool for this function */
} F;
/* Segment name for tentantive global definitions */
const char* BssName;
/* Label name for static symbols */
struct {
unsigned Label;
Collection *DefsOrRefs;
struct CodeEntry *IndJumpFrom;
} L;
/* Value of SP adjustment needed after forward 'goto' */
unsigned short SPAdjustment;
/* Data for anonymous struct or union members */
struct {
int Offs; /* Byte offset into struct */
unsigned ANumber; /* Numeric ID */
SymEntry* Field; /* The real field aliased */
} A;
/* Data for structs/unions tags */
struct {
struct SymTable* SymTab; /* Member symbol table */
unsigned Size; /* Size of the union/struct */
unsigned ACount; /* Count of anonymous fields */
} S;
/* Data for enums tags */
struct {
struct SymTable* SymTab; /* Member symbol table */
const Type* Type; /* Underlying type */
} E;
} V;
char Name[1]; /* Name, dynamically allocated */
char Name[1]; /* Name, dynamically allocated */
};
@@ -299,32 +298,24 @@ INLINE int SymHasAttr (const SymEntry* Sym, DeclAttrType A)
# define SymHasAttr(Sym, A) (SymGetAttr (Sym, A) != 0)
#endif
void SymUseAttr (SymEntry* Sym, struct Declaration* D);
/* Use the attributes from the declaration for this symbol */
void SymUseAttr (SymEntry* Sym, struct Declarator* D);
/* Use the attributes from the declarator for this symbol */
void SymSetAsmName (SymEntry* Sym);
/* Set the assembler name for an external symbol from the name of the symbol */
/* Set the assembler name for an external symbol from the name of the symbol.
** The symbol must have no assembler name set yet.
*/
void CvtRegVarToAuto (SymEntry* Sym);
void SymCvtRegVarToAuto (SymEntry* Sym);
/* Convert a register variable to an auto variable */
SymEntry* GetSymType (const Type* T);
/* Get the symbol entry of the enum/struct/union type
** Return 0 if it is not an enum/struct/union.
*/
const char* GetSymTypeName (const Type* T);
/* Return a name string of the type or the symbol name if it is an ESU type.
** Note: This may use a static buffer that could be overwritten by other calls.
*/
void ChangeSymType (SymEntry* Entry, const Type* T);
void SymChangeType (SymEntry* Sym, const Type* T);
/* Change the type of the given symbol */
void ChangeAsmName (SymEntry* Entry, const char* NewAsmName);
void SymChangeAsmName (SymEntry* Sym, const char* NewAsmName);
/* Change the assembler name of the symbol */
int HasAnonName (const SymEntry* Entry);
int SymHasAnonName (const SymEntry* Sym);
/* Return true if the symbol entry has an anonymous name */

View File

@@ -567,6 +567,11 @@ static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
/* Try to find the symbol in this table */
SymEntry* E = FindSymInTable (Tab, Name, Hash);
while (E != 0 && (E->Flags & SC_ALIAS) == SC_ALIAS) {
/* Get the aliased entry */
E = E->V.A.Field;
}
/* Bail out if we found it */
if (E != 0) {
return E;
@@ -620,8 +625,8 @@ SymEntry FindStructField (const Type* T, const char* Name)
** value, or an empty entry struct if the field is not found.
*/
{
SymEntry* Entry = 0;
SymEntry Field;
SymEntry* Field = 0;
SymEntry Res;
int Offs = 0;
/* The given type may actually be a pointer to struct/union */
@@ -632,35 +637,35 @@ SymEntry FindStructField (const Type* T, const char* Name)
/* Only structs/unions have struct/union fields... */
if (IsClassStruct (T)) {
/* Get a pointer to the struct/union type */
const SymEntry* Struct = GetESUSymEntry (T);
CHECK (Struct != 0);
/* Get a pointer to the struct/union tag */
const SymEntry* TagSym = GetESUTagSym (T);
CHECK (TagSym != 0);
/* Now search in the struct/union symbol table. Beware: The table may
** not exist.
*/
if (Struct->V.S.SymTab) {
Entry = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
if (TagSym->V.S.SymTab) {
Field = FindSymInTable (TagSym->V.S.SymTab, Name, HashStr (Name));
if (Entry != 0) {
Offs = Entry->V.Offs;
if (Field != 0) {
Offs = Field->V.Offs;
}
while (Entry != 0 && (Entry->Flags & SC_ALIAS) == SC_ALIAS) {
while (Field != 0 && (Field->Flags & SC_ALIAS) == SC_ALIAS) {
/* Get the real field */
Entry = Entry->V.A.Field;
Field = Field->V.A.Field;
}
}
}
if (Entry != 0) {
Field = *Entry;
Field.V.Offs = Offs;
if (Field != 0) {
Res = *Field;
Res.V.Offs = Offs;
} else {
memset (&Field, 0, sizeof(SymEntry));
memset (&Res, 0, sizeof(SymEntry));
}
return Field;
return Res;
}
@@ -684,15 +689,15 @@ static int IsDistinctRedef (const Type* lhst, const Type* rhst, typecmpcode_t Co
}
static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags)
static int HandleSymRedefinition (SymEntry* Sym, const Type* T, unsigned Flags)
/* Check and handle redefinition of existing symbols.
** Complete array sizes and function descriptors as well.
** Return true if there *is* an error.
*/
{
/* Get the type info of the existing symbol */
Type* E_Type = Entry->Type;
unsigned E_SCType = Entry->Flags & SC_TYPEMASK;
Type* E_Type = Sym->Type;
unsigned E_SCType = Sym->Flags & SC_TYPEMASK;
unsigned SCType = Flags & SC_TYPEMASK;
/* Some symbols may be redeclared if certain requirements are met */
@@ -701,15 +706,16 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
/* Existing typedefs cannot be redeclared as anything different */
if (SCType == SC_TYPEDEF) {
if (IsDistinctRedef (E_Type, T, TC_IDENTICAL, TCF_MASK_QUAL)) {
Error ("Conflicting types for typedef '%s'", Entry->Name);
Entry = 0;
Error ("Conflicting types for typedef '%s'", Sym->Name);
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
Sym = 0;
}
} else {
Error ("Redefinition of typedef '%s' as different kind of symbol", Entry->Name);
Entry = 0;
Error ("Redefinition of typedef '%s' as different kind of symbol", Sym->Name);
Sym = 0;
}
} else if ((Entry->Flags & SC_FUNC) == SC_FUNC) {
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
/* In case of a function, use the new type descriptor, since it
** contains pointers to the new symbol tables that are needed if
@@ -720,27 +726,27 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
if (IsTypeFunc (T)) {
/* Check for duplicate function definitions */
if (SymIsDef (Entry) && (Flags & SC_DEF) == SC_DEF) {
if (SymIsDef (Sym) && (Flags & SC_DEF) == SC_DEF) {
Error ("Body for function '%s' has already been defined",
Entry->Name);
Entry = 0;
Sym->Name);
Sym = 0;
} else {
/* New type must be compatible with the composite prototype */
if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) {
Error ("Conflicting function types for '%s'", Entry->Name);
TypeCompatibilityDiagnostic (T, E_Type, 0, "'%s' vs '%s'");
Entry = 0;
Error ("Conflicting function types for '%s'", Sym->Name);
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
Sym = 0;
} else {
/* Refine the existing composite prototype with this new
** one.
*/
RefineFuncDesc (Entry->Type, T);
RefineFuncDesc (Sym->Type, T);
}
}
} else {
Error ("Redefinition of function '%s' as different kind of symbol", Entry->Name);
Entry = 0;
Error ("Redefinition of function '%s' as different kind of symbol", Sym->Name);
Sym = 0;
}
} else {
@@ -759,8 +765,9 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
IsDistinctRedef (E_Type + 1, T + 1, TC_IDENTICAL, TCF_MASK_QUAL)) {
/* Conflicting element types */
Error ("Conflicting array types for '%s[]'", Entry->Name);
Entry = 0;
Error ("Conflicting array types for '%s[]'", Sym->Name);
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
Sym = 0;
} else {
/* Check if we have a size in the existing definition */
if (ESize == UNSPECIFIED) {
@@ -773,24 +780,25 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
/* New type must be equivalent */
if (SCType != E_SCType) {
Error ("Redefinition of '%s' as different kind of symbol", Entry->Name);
Entry = 0;
Error ("Redefinition of '%s' as different kind of symbol", Sym->Name);
Sym = 0;
} else if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) {
Error ("Conflicting types for '%s'", Entry->Name);
Entry = 0;
Error ("Conflicting types for '%s'", Sym->Name);
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
Sym = 0;
} else if (E_SCType == SC_ENUMERATOR) {
/* Enumerators aren't allowed to be redeclared at all, even if
** all occurences are identical. The current code logic won't
** get here, but let's just do it.
*/
Error ("Redeclaration of enumerator constant '%s'", Entry->Name);
Entry = 0;
Error ("Redeclaration of enumerator constant '%s'", Sym->Name);
Sym = 0;
}
}
}
/* Return if there are any errors */
return Entry == 0;
return Sym == 0;
}
@@ -824,38 +832,38 @@ static void AddSymEntry (SymTable* T, SymEntry* S)
SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags)
/* Add an enum entry and return it */
/* Add an enum tag entry and return it */
{
SymTable* CurTagTab = TagTab;
SymEntry* Entry;
SymEntry* TagEntry;
if ((Flags & SC_FICTITIOUS) == 0) {
/* Do we have an entry with this name already? */
Entry = FindSymInTable (CurTagTab, Name, HashStr (Name));
TagEntry = FindSymInTable (CurTagTab, Name, HashStr (Name));
} else {
/* Add a fictitious symbol in the fail-safe table */
Entry = 0;
TagEntry = 0;
CurTagTab = FailSafeTab;
}
if (Entry) {
if (TagEntry) {
/* We do have an entry. This may be a forward, so check it. */
if ((Entry->Flags & SC_TYPEMASK) != SC_ENUM) {
if ((TagEntry->Flags & SC_TYPEMASK) != SC_ENUM) {
/* Existing symbol is not an enum */
Error ("Symbol '%s' is already different kind", Name);
Entry = 0;
TagEntry = 0;
} else if (Type != 0) {
/* Define the struct size if the underlying type is given. */
if (Entry->V.E.Type != 0) {
if (TagEntry->V.E.Type != 0) {
/* Both are definitions. */
Error ("Multiple definition for 'enum %s'", Name);
Entry = 0;
TagEntry = 0;
} else {
Entry->V.E.SymTab = Tab;
Entry->V.E.Type = Type;
Entry->Flags &= ~SC_DECL;
Entry->Flags |= SC_DEF;
TagEntry->V.E.SymTab = Tab;
TagEntry->V.E.Type = Type;
TagEntry->Flags &= ~SC_DECL;
TagEntry->Flags |= SC_DEF;
/* Remember this is the first definition of this type */
if (DSFlags != 0) {
@@ -864,83 +872,83 @@ SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTab
}
}
if (Entry == 0) {
if (TagEntry == 0) {
/* Use the fail-safe table for fictitious symbols */
CurTagTab = FailSafeTab;
}
}
if (Entry == 0) {
if (TagEntry == 0) {
/* Create a new entry */
Entry = NewSymEntry (Name, SC_ENUM);
TagEntry = NewSymEntry (Name, SC_ENUM);
/* Set the enum type data */
Entry->V.E.SymTab = Tab;
Entry->V.E.Type = Type;
TagEntry->V.E.SymTab = Tab;
TagEntry->V.E.Type = Type;
if (Type != 0) {
Entry->Flags |= SC_DEF;
TagEntry->Flags |= SC_DEF;
}
/* Remember this is the first definition of this type */
if (CurTagTab != FailSafeTab && DSFlags != 0) {
if ((Entry->Flags & SC_DEF) != 0) {
if ((TagEntry->Flags & SC_DEF) != 0) {
*DSFlags |= DS_NEW_TYPE_DEF;
}
*DSFlags |= DS_NEW_TYPE_DECL;
}
/* Add it to the current table */
AddSymEntry (CurTagTab, Entry);
AddSymEntry (CurTagTab, TagEntry);
}
/* Return the entry */
return Entry;
return TagEntry;
}
SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags)
/* Add a struct/union entry and return it */
/* Add a struct/union tag entry and return it */
{
SymTable* CurTagTab = TagTab;
SymEntry* Entry;
unsigned Type = (Flags & SC_TYPEMASK);
SymEntry* TagEntry;
unsigned SCType = (Flags & SC_TYPEMASK);
/* Type must be struct or union */
PRECONDITION (Type == SC_STRUCT || Type == SC_UNION);
/* SCType must be struct or union */
PRECONDITION (SCType == SC_STRUCT || SCType == SC_UNION);
if ((Flags & SC_FICTITIOUS) == 0) {
/* Do we have an entry with this name already? */
Entry = FindSymInTable (CurTagTab, Name, HashStr (Name));
TagEntry = FindSymInTable (CurTagTab, Name, HashStr (Name));
} else {
/* Add a fictitious symbol in the fail-safe table */
Entry = 0;
TagEntry = 0;
CurTagTab = FailSafeTab;
}
if (Entry) {
if (TagEntry) {
/* We do have an entry. This may be a forward, so check it. */
if ((Entry->Flags & SC_TYPEMASK) != Type) {
if ((TagEntry->Flags & SC_TYPEMASK) != SCType) {
/* Existing symbol is not a struct */
Error ("Symbol '%s' is already different kind", Name);
Entry = 0;
} else if ((Entry->Flags & Flags & SC_DEF) == SC_DEF) {
TagEntry = 0;
} else if ((TagEntry->Flags & Flags & SC_DEF) == SC_DEF) {
/* Both structs are definitions. */
if (Type == SC_STRUCT) {
if (SCType == SC_STRUCT) {
Error ("Multiple definition for 'struct %s'", Name);
} else {
Error ("Multiple definition for 'union %s'", Name);
}
Entry = 0;
TagEntry = 0;
} else {
/* Define the struct size if it is a definition */
if ((Flags & SC_DEF) == SC_DEF) {
Entry->Flags = Flags;
Entry->V.S.SymTab = Tab;
Entry->V.S.Size = Size;
TagEntry->Flags = Flags;
TagEntry->V.S.SymTab = Tab;
TagEntry->V.S.Size = Size;
/* Remember this is the first definition of this type */
if (DSFlags != 0) {
@@ -949,35 +957,35 @@ SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTabl
}
}
if (Entry == 0) {
if (TagEntry == 0) {
/* Use the fail-safe table for fictitious symbols */
CurTagTab = FailSafeTab;
}
}
if (Entry == 0) {
if (TagEntry == 0) {
/* Create a new entry */
Entry = NewSymEntry (Name, Flags);
TagEntry = NewSymEntry (Name, Flags);
/* Set the struct data */
Entry->V.S.SymTab = Tab;
Entry->V.S.Size = Size;
TagEntry->V.S.SymTab = Tab;
TagEntry->V.S.Size = Size;
/* Remember this is the first definition of this type */
if (CurTagTab != FailSafeTab && DSFlags != 0) {
if ((Entry->Flags & SC_DEF) != 0) {
if ((TagEntry->Flags & SC_DEF) != 0) {
*DSFlags |= DS_NEW_TYPE_DEF;
}
*DSFlags |= DS_NEW_TYPE_DECL;
}
/* Add it to the current tag table */
AddSymEntry (CurTagTab, Entry);
AddSymEntry (CurTagTab, TagEntry);
}
/* Return the entry */
return Entry;
return TagEntry;
}
@@ -1068,7 +1076,7 @@ DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags)
DOR = xmalloc (sizeof (DefOrRef));
CollAppend (E->V.L.DefsOrRefs, DOR);
DOR->Line = GetCurrentLine ();
DOR->Line = GetCurrentLineNum ();
DOR->LocalsBlockId = (size_t)CollLast (&CurrentFunc->LocalsBlockStack);
DOR->Flags = Flags;
DOR->StackPtr = StackPtr;
@@ -1136,7 +1144,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
(size_t)CollAt (AIC, DOR->Depth - 1) != DOR->LocalsBlockId)) {
Warning ("Goto at line %d to label %s jumps into a block with "
"initialization of an object that has automatic storage duration",
GetCurrentLine (), Name);
GetCurrentLineNum (), Name);
}
}
@@ -1279,6 +1287,11 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
/* Generate the assembler name from the data label number */
Entry->V.L.Label = Offs;
Entry->AsmName = xstrdup (LocalDataLabelName (Entry->V.L.Label));
} else if ((Flags & SC_ALIAS) == SC_ALIAS) {
/* Just clear the info */
Entry->V.A.Field = 0;
Entry->V.A.ANumber = 0;
Entry->V.A.Offs = 0;
} else {
Internal ("Invalid flags in AddLocalSym: %04X", Flags);
}
@@ -1296,13 +1309,26 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
/* Add an external or global symbol to the symbol table and return the entry */
{
/* Start from the local symbol table */
SymTable* Tab = SymTab;
/* Add the new declaration to the global symbol table if no errors */
SymTable* Tab = SymTab0;
/* Only search this name in the local and global symbol tables */
SymEntry* Entry = 0;
SymEntry* Alias = 0;
if (SymTab != SymTab0) {
Alias = Entry = FindLocalSym (Name);
while (Entry && (Entry->Flags & SC_ALIAS) == SC_ALIAS) {
/* Get the aliased entry */
Entry = Entry->V.A.Field;
}
}
if (Entry == 0) {
Entry = FindGlobalSym (Name);
}
/* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTree (Tab, Name);
if (Entry) {
/* We have a symbol with this name already */
if (HandleSymRedefinition (Entry, T, Flags)) {
Entry = 0;
@@ -1317,7 +1343,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
** declaration if both declarations are global, otherwise give an
** error.
*/
if (Tab == SymTab0 &&
if (SymTab == SymTab0 &&
(Flags & SC_EXTERN) == 0 &&
(Entry->Flags & SC_EXTERN) != 0) {
Warning ("Static declaration of '%s' follows non-static declaration", Name);
@@ -1353,12 +1379,9 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
/* Use the fail-safe table for fictitious symbols */
Tab = FailSafeTab;
}
} else if ((Flags & (SC_EXTERN | SC_FUNC)) != 0) {
/* Add the new declaration to the global symbol table instead */
Tab = SymTab0;
}
if (Entry == 0 || Entry->Owner != Tab) {
if (Entry == 0) {
/* Create a new entry */
Entry = NewSymEntry (Name, Flags);
@@ -1376,6 +1399,13 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
/* Add the entry to the symbol table */
AddSymEntry (Tab, Entry);
}
/* Add an alias of the global symbol to the local symbol table */
if (Tab == SymTab0 && SymTab != SymTab0 && Entry->Owner != SymTab && Alias == 0) {
Alias = AddLocalSym (Name, T, SC_ALIAS, 0);
Alias->V.A.Field = Entry;
}
/* Return the entry */

View File

@@ -169,10 +169,10 @@ unsigned short FindSPAdjustment (const char* Name);
SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags);
/* Add an enum entry and return it */
/* Add an enum tag entry and return it */
SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags);
/* Add a struct/union entry and return it */
/* Add a struct/union tag entry and return it */
SymEntry* AddBitField (const char* Name, const Type* Type, unsigned Offs,
unsigned BitOffs, unsigned BitWidth, int SignednessSpecified);

View File

@@ -266,18 +266,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
LeftType = (GetUnderlyingTypeCode (lhs) & T_MASK_TYPE);
RightType = (GetUnderlyingTypeCode (rhs) & T_MASK_TYPE);
/* If one side is a pointer and the other side is an array, both are
** compatible.
*/
if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
RightType = T_TYPE_PTR;
SetResult (Result, TC_PTR_DECAY);
}
if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) {
LeftType = T_TYPE_PTR;
SetResult (Result, TC_STRICT_COMPATIBLE);
}
/* Bit-fields are considered compatible if they have the same
** signedness, bit-offset and bit-width.
*/
@@ -287,12 +275,27 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
lhs->A.B.Offs != rhs->A.B.Offs ||
lhs->A.B.Width != rhs->A.B.Width) {
SetResult (Result, TC_INCOMPATIBLE);
return;
}
if (LeftType != RightType) {
SetResult (Result, TC_STRICT_COMPATIBLE);
}
}
/* If one side is a pointer and the other side is an array, both are
** compatible.
*/
if (Result->Indirections == 0) {
if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
RightType = T_TYPE_PTR;
SetResult (Result, TC_PTR_DECAY);
}
if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) {
LeftType = T_TYPE_PTR;
SetResult (Result, TC_STRICT_COMPATIBLE);
}
}
/* If the underlying types are not identical, the types are incompatible */
if (LeftType != RightType) {
SetResult (Result, TC_INCOMPATIBLE);
@@ -303,8 +306,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
if ((IsTypeEnum (lhs) || IsTypeEnum (rhs))) {
/* Compare the tag types */
Sym1 = IsTypeEnum (lhs) ? GetESUSymEntry (lhs) : 0;
Sym2 = IsTypeEnum (rhs) ? GetESUSymEntry (rhs) : 0;
Sym1 = IsTypeEnum (lhs) ? GetESUTagSym (lhs) : 0;
Sym2 = IsTypeEnum (rhs) ? GetESUTagSym (rhs) : 0;
if (Sym1 != Sym2) {
if (Sym1 == 0 || Sym2 == 0) {
@@ -420,8 +423,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
case T_TYPE_STRUCT:
case T_TYPE_UNION:
/* Compare the tag types */
Sym1 = GetESUSymEntry (lhs);
Sym2 = GetESUSymEntry (rhs);
Sym1 = GetESUTagSym (lhs);
Sym2 = GetESUTagSym (rhs);
CHECK (Sym1 != 0 || Sym2 != 0);

View File

@@ -44,14 +44,20 @@
#if defined(__GNUC__)
# define attribute(a) __attribute__(a)
#ifdef __clang__
# define attribute(a) __attribute__(a)
# define ATTR_UNUSED(x) __attribute__((__unused__)) x
# define ATTR_NORETURN __attribute__((analyzer_noreturn))
#elif defined(__GNUC__)
# define attribute(a) __attribute__(a)
# define ATTR_UNUSED(x) __attribute__((__unused__)) x
# define ATTR_NORETURN __attribute__((noreturn))
#else
# define attribute(a)
# define ATTR_UNUSED(x) x
# define ATTR_NORETURN
#endif
/* End of attrib.h */
#endif

View File

@@ -592,9 +592,19 @@ static void RangeSection (void)
case INFOTOK_END:
AddAttr ("END", &Attributes, tEnd);
InfoNextTok ();
InfoAssureInt ();
InfoRangeCheck (0x0000, 0xFFFF);
End = InfoIVal;
if (InfoTok == INFOTOK_OFFSET_INTCON) {
InfoRangeCheck (0x0000, 0xFFFF);
if (!(Attributes & tStart))
InfoError ("When using End with an offset, Start must be specified before");
End = Start + InfoIVal - 1;
if (End > 0xFFFF)
InfoError ("Range error");
} else {
InfoAssureInt ();
InfoRangeCheck (0x0000, 0xFFFF);
End = InfoIVal;
}
InfoNextTok ();
break;

View File

@@ -372,6 +372,14 @@ Again:
return;
}
/* Decimal number offset? */
if (C == '+') {
NextChar ();
InfoIVal = GetDecimalToken ();
InfoTok = INFOTOK_OFFSET_INTCON;
return;
}
/* Other characters */
switch (C) {

View File

@@ -48,6 +48,7 @@
typedef enum token_t {
INFOTOK_NONE,
INFOTOK_INTCON,
INFOTOK_OFFSET_INTCON,
INFOTOK_STRCON,
INFOTOK_CHARCON,
INFOTOK_IDENT,

View File

@@ -46,7 +46,7 @@
/* THE memory */
static unsigned char Mem[0x10000];
unsigned char Mem[0x10000];
@@ -73,14 +73,6 @@ void MemWriteWord (unsigned Addr, unsigned Val)
unsigned char MemReadByte (unsigned Addr)
/* Read a byte from a memory location */
{
return Mem[Addr];
}
unsigned MemReadWord (unsigned Addr)
/* Read a word from a memory location */
{

View File

@@ -36,7 +36,9 @@
#ifndef MEMORY_H
#define MEMORY_H
#include "inline.h"
extern unsigned char Mem[0x10000];
/*****************************************************************************/
/* Code */
@@ -50,8 +52,15 @@ void MemWriteByte (unsigned Addr, unsigned char Val);
void MemWriteWord (unsigned Addr, unsigned Val);
/* Write a word to a memory location */
unsigned char MemReadByte (unsigned Addr);
#if defined(HAVE_INLINE)
INLINE unsigned char MemReadByte (unsigned Addr)
/* Read a byte from a memory location */
{
return Mem[Addr];
}
#else
#define MemReadByte(Addr) Mem[Addr]
#endif
unsigned MemReadWord (unsigned Addr);
/* Read a word from a memory location */