-unsigned assignadjust (type* lhst, ExprDesc* rhs)
-/* Adjust the type of the right hand expression so that it can be assigned to
- * the type on the left hand side. This function is used for assignment and
- * for converting parameters in a function call. It returns the code generator
- * flags for the operation. The type string of the right hand side will be
- * set to the type of the left hand side.
- */
-{
- /* Get the type of the right hand side. Treat function types as
- * pointer-to-function
- */
- type* rhst = rhs->Type;
- if (IsTypeFunc (rhst)) {
- rhst = PointerTo (rhst);
- }
-
- /* After calling this function, rhs will have the type of the lhs */
- rhs->Type = lhst;
-
- /* First, do some type checking */
- if (IsTypeVoid (lhst) || IsTypeVoid (rhst)) {
- /* If one of the sides are of type void, output a more apropriate
- * error message.
- */
- Error ("Illegal type");
- } else if (IsClassInt (lhst)) {
- if (IsClassPtr (rhst)) {
- /* Pointer -> int conversion */
- Warning ("Converting pointer to integer without a cast");
- } else if (!IsClassInt (rhst)) {
- Error ("Incompatible types");
- } else {
- /* Convert the rhs to the type of the lhs. */
- unsigned flags = TypeOf (rhst);
- if (rhs->Flags == E_MCONST) {
- flags |= CF_CONST;
- }
- return g_typecast (TypeOf (lhst), flags);
- }
- } else if (IsClassPtr (lhst)) {
- if (IsClassPtr (rhst)) {
- /* Pointer to pointer assignment is valid, if:
- * - both point to the same types, or
- * - the rhs pointer is a void pointer, or
- * - the lhs pointer is a void pointer.
- */
- if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) {
- /* Compare the types */
- switch (TypeCmp (lhst, rhst)) {
-
- case TC_INCOMPATIBLE:
- Error ("Incompatible pointer types");
- break;
-
- case TC_QUAL_DIFF:
- Error ("Pointer types differ in type qualifiers");
- break;
-
- default:
- /* Ok */
- break;
- }
- }
- } else if (IsClassInt (rhst)) {
- /* Int to pointer assignment is valid only for constant zero */
- if (rhs->Flags != E_MCONST || rhs->ConstVal != 0) {
- Warning ("Converting integer to pointer without a cast");
- }
- } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
- /* Assignment of function to function pointer is allowed, provided
- * that both functions have the same parameter list.
- */
- if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
- Error ("Incompatible types");
- }
- } else {
- Error ("Incompatible types");
- }
- } else {
- Error ("Incompatible types");
- }
-
- /* Return an int value in all cases where the operands are not both ints */
- return CF_INT;
-}
-
-
-
-void DefineData (ExprDesc* Expr)
-/* Output a data definition for the given expression */
-{
- unsigned Flags = Expr->Flags;
-
- switch (Flags & E_MCTYPE) {
-
- case E_TCONST:
- /* Number */
- g_defdata (TypeOf (Expr->Type) | CF_CONST, Expr->ConstVal, 0);
- break;
-
- case E_TREGISTER:
- /* Register variable. Taking the address is usually not
- * allowed.
- */
- if (!AllowRegVarAddr) {
- Error ("Cannot take the address of a register variable");
- }
- /* FALLTHROUGH */
-
- case E_TGLAB:
- case E_TLLAB:
- /* Local or global symbol */
- g_defdata (GlobalModeFlags (Flags), Expr->Name, Expr->ConstVal);
- break;
-
- case E_TLIT:
- /* a literal of some kind */
- g_defdata (CF_STATIC, LiteralPoolLabel, Expr->ConstVal);
- break;
-
- default:
- Internal ("Unknown constant type: %04X", Flags);
- }
-}
-
-
-
-static void LoadConstant (unsigned Flags, ExprDesc* Expr)
-/* Load the primary register with some constant value. */
-{
- switch (Expr->Flags & E_MCTYPE) {
-
- case E_TLOFFS:
- g_leasp (Expr->ConstVal);
- break;
-
- case E_TCONST:
- /* Number constant */
- g_getimmed (Flags | TypeOf (Expr->Type) | CF_CONST, Expr->ConstVal, 0);
- break;
-
- case E_TREGISTER:
- /* Register variable. Taking the address is usually not
- * allowed.
- */
- if (!AllowRegVarAddr) {
- Error ("Cannot take the address of a register variable");
- }
- /* FALLTHROUGH */
-
- case E_TGLAB:
- case E_TLLAB:
- /* Local or global symbol, load address */
- Flags |= GlobalModeFlags (Expr->Flags);
- Flags &= ~CF_CONST;
- g_getimmed (Flags, Expr->Name, Expr->ConstVal);
- break;
-
- case E_TLIT:
- /* Literal string */
- g_getimmed (CF_STATIC, LiteralPoolLabel, Expr->ConstVal);
- break;
-
- default:
- Internal ("Unknown constant type: %04X", Expr->Flags);
- }
-}
-
-
-
-static int kcalc (int tok, long val1, long val2)
-/* Calculate an operation with left and right operand constant. */
-{
- switch (tok) {
- case TOK_EQ:
- return (val1 == val2);
- case TOK_NE:
- return (val1 != val2);
- case TOK_LT:
- return (val1 < val2);
- case TOK_LE:
- return (val1 <= val2);
- case TOK_GE:
- return (val1 >= val2);
- case TOK_GT:
- return (val1 > val2);
- case TOK_OR:
- return (val1 | val2);
- case TOK_XOR:
- return (val1 ^ val2);
- case TOK_AND:
- return (val1 & val2);
- case TOK_SHR:
- return (val1 >> val2);
- case TOK_SHL:
- return (val1 << val2);
- case TOK_STAR:
- return (val1 * val2);
- case TOK_DIV:
- if (val2 == 0) {
- Error ("Division by zero");
- return 0x7FFFFFFF;
- }
- return (val1 / val2);
- case TOK_MOD:
- if (val2 == 0) {
- Error ("Modulo operation with zero");
- return 0;
- }
- return (val1 % val2);
- default:
- Internal ("kcalc: got token 0x%X\n", tok);
- return 0;
- }
-}
-
-
-
-static const GenDesc* FindGen (token_t Tok, const GenDesc** Table)