1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-27 15:29:46 +00:00

Organized ExprDesc functions and fixed several comments.

This commit is contained in:
acqn 2022-10-24 14:55:39 +08:00
parent ad7c5a6617
commit b81e54c1d2
2 changed files with 387 additions and 330 deletions

View File

@ -67,75 +67,9 @@ ExprDesc* ED_Init (ExprDesc* Expr)
#if !defined(HAVE_INLINE) /*****************************************************************************/
int ED_IsLocQuasiConst (const ExprDesc* Expr) /* Info Extraction */
/* 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) && !ED_IsLocPrimary (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);
}
@ -215,6 +149,190 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
/*****************************************************************************/
/* 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.
*/
{
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) && !ED_IsLocPrimary (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));
}
#if !defined(HAVE_INLINE)
int ED_IsAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a numeric value or address. */
{
return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) ||
(Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF);
}
#endif
#if !defined(HAVE_INLINE)
int ED_IsConstAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a constant absolute value. This can be
** a numeric constant, cast to any type.
*/
{
return ED_IsRVal (Expr) && ED_IsAbs (Expr);
}
#endif
int ED_IsConstAbsInt (const ExprDesc* Expr)
/* Return true if the expression is a constant (numeric) integer. */
{
return ED_IsConstAbs (Expr) && IsClassInt (Expr->Type);
}
int ED_IsConstBool (const ExprDesc* Expr)
/* Return true if the expression can be constantly evaluated as a boolean. */
{
return ED_IsConstAbsInt (Expr) || ED_IsAddrExpr (Expr);
}
int ED_IsConstTrue (const ExprDesc* Expr)
/* Return true if the constant expression can be evaluated as boolean true at
** compile time.
*/
{
/* Non-zero arithmetics and objects addresses are boolean true */
return (ED_IsConstAbsInt (Expr) && Expr->IVal != 0) ||
(ED_IsAddrExpr (Expr));
}
int ED_IsConstFalse (const ExprDesc* Expr)
/* Return true if the constant expression can be evaluated as boolean false at
** compile time.
*/
{
/* Zero arithmetics and null pointers are boolean false */
return (ED_IsConstAbsInt (Expr) && Expr->IVal == 0) ||
ED_IsNullPtr (Expr);
}
int ED_IsConst (const ExprDesc* Expr)
/* Return true if the expression denotes a constant of some sort. This can be a
** numeric constant, the address of a global variable (maybe with offset) or
** similar.
*/
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsConstAddr (Expr);
}
int ED_IsQuasiConst (const ExprDesc* Expr)
/* Return true if the expression denotes a quasi-constant of some sort. This
** can be a numeric constant, a constant address or a stack variable address.
*/
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsQuasiConstAddr (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.
*/
{
return ED_IsAddrExpr (Expr) && ED_IsLocConst (Expr);
}
int ED_IsQuasiConstAddr (const ExprDesc* Expr)
/* Return true if the expression denotes a quasi-constant address of some sort.
** This can be a constant address or a stack variable address.
*/
{
return ED_IsAddrExpr (Expr) && ED_IsLocQuasiConst (Expr);
}
int ED_IsNullPtr (const ExprDesc* Expr)
/* Return true if the given expression is a NULL pointer constant */
{
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) ==
(E_LOC_NONE|E_RTYPE_RVAL) &&
Expr->IVal == 0 &&
IsClassInt (Expr->Type);
}
int ED_IsBool (const ExprDesc* Expr)
/* Return true if the expression can be treated as a boolean, that is, it can
** be an operand to a compare operation.
*/
{
/* Either ints, floats, or pointers can be used in a boolean context */
return IsClassInt (Expr->Type) ||
IsClassFloat (Expr->Type) ||
IsClassPtr (Expr->Type) ||
IsClassFunc (Expr->Type);
}
/*****************************************************************************/
/* Manipulation */
/*****************************************************************************/
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type) ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, const Type* Type)
/* Replace Expr with an absolute const with the given value and type */ /* Replace Expr with an absolute const with the given value and type */
{ {
@ -331,7 +449,7 @@ ExprDesc* ED_IndExpr (ExprDesc* Expr)
** original address. We simply mark this as E_LOC_EXPR so that ** original address. We simply mark this as E_LOC_EXPR so that
** some info about the original location can be retained. ** some info about the original location can be retained.
** If it's really meant to dereference a "pointer value", it ** If it's really meant to dereference a "pointer value", it
** should be done in two steps where the pointervalue should ** should be done in two steps where the pointer value should
** be the manually loaded first before a call into this, and ** be the manually loaded first before a call into this, and
** the offset should be manually cleared somewhere outside. ** the offset should be manually cleared somewhere outside.
*/ */
@ -345,131 +463,27 @@ ExprDesc* ED_IndExpr (ExprDesc* Expr)
#if !defined(HAVE_INLINE) void ED_MarkForUneval (ExprDesc* Expr)
int ED_IsAbs (const ExprDesc* Expr) /* Mark the expression as not to be evaluated */
/* Return true if the expression denotes a numeric value or address. */
{ {
return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) || Expr->Flags = (Expr->Flags & ~E_MASK_EVAL) | E_EVAL_UNEVAL;
(Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF);
}
#endif
#if !defined(HAVE_INLINE)
int ED_IsConstAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a constant absolute value. This can be
** a numeric constant, cast to any type.
*/
{
return ED_IsRVal (Expr) && ED_IsAbs (Expr);
}
#endif
int ED_IsConstAbsInt (const ExprDesc* Expr)
/* Return true if the expression is a constant (numeric) integer. */
{
return ED_IsConstAbs (Expr) && IsClassInt (Expr->Type);
} }
int ED_IsConstBool (const ExprDesc* Expr) const Type* ReplaceType (ExprDesc* Expr, const Type* NewType)
/* Return true if the expression can be constantly evaluated as a boolean. */ /* Replace the type of Expr by a copy of Newtype and return the old type string */
{ {
return ED_IsConstAbsInt (Expr) || ED_IsAddrExpr (Expr); const Type* OldType = Expr->Type;
Expr->Type = TypeDup (NewType);
return OldType;
} }
int ED_IsConstTrue (const ExprDesc* Expr) /*****************************************************************************/
/* Return true if the constant expression can be evaluated as boolean true at /* Other Helpers */
** compile time. /*****************************************************************************/
*/
{
/* Non-zero arithmetics and objects addresses are boolean true */
return (ED_IsConstAbsInt (Expr) && Expr->IVal != 0) ||
(ED_IsAddrExpr (Expr));
}
int ED_IsConstFalse (const ExprDesc* Expr)
/* Return true if the constant expression can be evaluated as boolean false at
** compile time.
*/
{
/* Zero arithmetics and null pointers are boolean false */
return (ED_IsConstAbsInt (Expr) && Expr->IVal == 0) ||
ED_IsNullPtr (Expr);
}
int ED_IsConst (const ExprDesc* Expr)
/* Return true if the expression denotes a constant of some sort. This can be a
** numeric constant, the address of a global variable (maybe with offset) or
** similar.
*/
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsConstAddr (Expr);
}
int ED_IsQuasiConst (const ExprDesc* Expr)
/* Return true if the expression denotes a quasi-constant of some sort. This
** can be a numeric constant, a constant address or a stack variable address.
*/
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsQuasiConstAddr (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.
*/
{
return ED_IsAddrExpr (Expr) && ED_IsLocConst (Expr);
}
int ED_IsQuasiConstAddr (const ExprDesc* Expr)
/* Return true if the expression denotes a quasi-constant address of some sort.
** This can be a constant address or a stack variable address.
*/
{
return ED_IsAddrExpr (Expr) && ED_IsLocQuasiConst (Expr);
}
int ED_IsNullPtr (const ExprDesc* Expr)
/* Return true if the given expression is a NULL pointer constant */
{
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) ==
(E_LOC_NONE|E_RTYPE_RVAL) &&
Expr->IVal == 0 &&
IsClassInt (Expr->Type);
}
int ED_IsBool (const ExprDesc* Expr)
/* Return true if the expression can be treated as a boolean, that is, it can
** be an operand to a compare operation.
*/
{
/* Either ints, floats, or pointers can be used in a boolean context */
return IsClassInt (Expr->Type) ||
IsClassFloat (Expr->Type) ||
IsClassPtr (Expr->Type) ||
IsClassFunc (Expr->Type);
}
@ -577,10 +591,21 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
const Type* ReplaceType (ExprDesc* Expr, const Type* NewType) void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End)
/* Replace the type of Expr by a copy of Newtype and return the old type string */ /* Set the code range for this expression */
{ {
const Type* OldType = Expr->Type; Expr->Flags |= E_HAVE_MARKS;
Expr->Type = TypeDup (NewType); Expr->Start = *Start;
return OldType; 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); ExprDesc* ED_Init (ExprDesc* Expr);
/* Initialize an ExprDesc */ /* Initialize an ExprDesc */
/*****************************************************************************/
/* Info Extraction */
/*****************************************************************************/
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE int ED_GetLoc (const ExprDesc* Expr) INLINE int ED_GetLoc (const ExprDesc* Expr)
/* Return the location flags from the expression */ /* 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) # define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC)
#endif #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) #if defined(HAVE_INLINE)
INLINE int ED_IsLocNone (const ExprDesc* Expr) INLINE int ED_IsLocNone (const ExprDesc* Expr)
/* Return true if the expression is an absolute value */ /* Return true if the expression is an absolute value */
@ -279,7 +316,7 @@ INLINE int ED_IsLocStack (const ExprDesc* Expr)
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE int ED_IsLocPrimary (const ExprDesc* Expr) 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; return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY;
} }
@ -289,7 +326,7 @@ INLINE int ED_IsLocPrimary (const ExprDesc* Expr)
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE int ED_IsLocExpr (const ExprDesc* Expr) 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; return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR;
} }
@ -333,33 +370,14 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr);
#endif #endif
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE void ED_RequireTest (ExprDesc* Expr) INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Mark the expression for a test. */ /* 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 #else
# define ED_RequireTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0) int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr);
#endif /* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
#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)
#endif #endif
#if defined(HAVE_INLINE) #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) # define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0)
#endif #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) #if defined(HAVE_INLINE)
INLINE int ED_IsTested (const ExprDesc* Expr) INLINE int ED_IsTested (const ExprDesc* Expr)
/* Check if the expression has set the condition codes. */ /* Check if the expression has set the condition codes. */
@ -414,13 +411,13 @@ INLINE int ED_IsTested (const ExprDesc* Expr)
#endif #endif
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE void ED_MarkAsUntested (ExprDesc* Expr) INLINE int ED_YetToTest (const ExprDesc* Expr)
/* Mark the expression as not tested (condition codes not set). */ /* 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 #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 #endif
#if defined(HAVE_INLINE) #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) # define ED_NeedsConst(Expr) (((Expr)->Flags & E_EVAL_IMMUTABLE_RESULT) == E_EVAL_IMMUTABLE_RESULT)
#endif #endif
void ED_MarkForUneval (ExprDesc* Expr);
/* Mark the expression as not to be evaluated */
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE int ED_IsUneval (const ExprDesc* Expr) INLINE int ED_IsUneval (const ExprDesc* Expr)
/* Check if the expression is not to be evaluated */ /* 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) # define ED_MayHaveNoEffect(Expr) (((Expr)->Flags & E_EVAL_MAYBE_UNUSED) == E_EVAL_MAYBE_UNUSED)
#endif #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) #if defined(HAVE_INLINE)
INLINE int ED_IsAddrExpr (const ExprDesc* Expr) INLINE int ED_IsAddrExpr (const ExprDesc* Expr)
/* Check if the expression is taken address of instead of its value. /* Check if the expression is taken address of instead of its value.
@ -515,35 +488,6 @@ int ED_IsIndExpr (const ExprDesc* Expr);
/* Check if the expression is a reference to its value */ /* Check if the expression is a reference to its value */
#endif #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) #if defined(HAVE_INLINE)
INLINE int ED_IsLVal (const ExprDesc* Expr) INLINE int ED_IsLVal (const ExprDesc* Expr)
/* Return true if the expression is a reference */ /* Return true if the expression is a reference */
@ -564,40 +508,6 @@ INLINE int ED_IsRVal (const ExprDesc* Expr)
# define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL) # define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL)
#endif #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) #if defined(HAVE_INLINE)
INLINE int ED_IsAbs (const ExprDesc* Expr) INLINE int ED_IsAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a numeric value or address. */ /* Return true if the expression denotes a numeric value or address. */
@ -670,14 +580,136 @@ int ED_IsBool (const ExprDesc* Expr);
** be an operand to a compare operation with 0/NULL. ** 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); const Type* ReplaceType (ExprDesc* Expr, const Type* NewType);
/* Replace the type of Expr by a copy of Newtype and return the old type string */ /* 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 */ /* End of exprdesc.h */
#endif #endif