|
|
1.1 ! root 1: /* Language-level data type conversion for GNU C. ! 2: Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: /* This file contains the functions for converting C expressions ! 22: to different data types. The only entry point is `convert'. ! 23: Every language front end must have a `convert' function ! 24: but what kind of conversions it does will depend on the language. */ ! 25: ! 26: #include "config.h" ! 27: #include "tree.h" ! 28: #include "flags.h" ! 29: ! 30: /* Change of width--truncation and extension of integers or reals-- ! 31: is represented with NOP_EXPR. Proper functioning of many things ! 32: assumes that no other conversions can be NOP_EXPRs. ! 33: ! 34: Conversion between integer and pointer is represented with CONVERT_EXPR. ! 35: Converting integer to real uses FLOAT_EXPR ! 36: and real to integer uses FIX_TRUNC_EXPR. ! 37: ! 38: Here is a list of all the functions that assume that widening and ! 39: narrowing is always done with a NOP_EXPR: ! 40: In c-convert.c, convert_to_integer. ! 41: In c-typeck.c, build_binary_op (boolean ops), and truthvalue_conversion. ! 42: In expr.c: expand_expr, for operands of a MULT_EXPR. ! 43: In fold-const.c: fold. ! 44: In tree.c: get_narrower and get_unwidened. */ ! 45: ! 46: /* Subroutines of `convert'. */ ! 47: ! 48: static tree ! 49: convert_to_pointer (type, expr) ! 50: tree type, expr; ! 51: { ! 52: register tree intype = TREE_TYPE (expr); ! 53: register enum tree_code form = TREE_CODE (intype); ! 54: ! 55: if (integer_zerop (expr)) ! 56: { ! 57: if (type == TREE_TYPE (null_pointer_node)) ! 58: return null_pointer_node; ! 59: expr = build_int_2 (0, 0); ! 60: TREE_TYPE (expr) = type; ! 61: return expr; ! 62: } ! 63: ! 64: if (form == POINTER_TYPE) ! 65: return build1 (NOP_EXPR, type, expr); ! 66: ! 67: ! 68: if (form == INTEGER_TYPE || form == ENUMERAL_TYPE) ! 69: { ! 70: if (type_precision (intype) == POINTER_SIZE) ! 71: return build1 (CONVERT_EXPR, type, expr); ! 72: expr = convert (type_for_size (POINTER_SIZE, 0), expr); ! 73: if (TYPE_MODE (TREE_TYPE (expr)) != TYPE_MODE (type)) ! 74: /* There is supposed to be some integral type ! 75: that is the same width as a pointer. */ ! 76: abort (); ! 77: return convert_to_pointer (type, expr); ! 78: } ! 79: ! 80: error ("cannot convert to a pointer type"); ! 81: ! 82: return null_pointer_node; ! 83: } ! 84: ! 85: static tree ! 86: convert_to_real (type, expr) ! 87: tree type, expr; ! 88: { ! 89: register enum tree_code form = TREE_CODE (TREE_TYPE (expr)); ! 90: ! 91: if (form == REAL_TYPE) ! 92: return build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR, ! 93: type, expr); ! 94: ! 95: if (form == INTEGER_TYPE || form == ENUMERAL_TYPE) ! 96: return build1 (FLOAT_EXPR, type, expr); ! 97: ! 98: if (form == POINTER_TYPE) ! 99: error ("pointer value used where a float was expected"); ! 100: else ! 101: error ("aggregate value used where a float was expected"); ! 102: ! 103: { ! 104: register tree tem = make_node (REAL_CST); ! 105: TREE_TYPE (tem) = type; ! 106: TREE_REAL_CST (tem) = REAL_VALUE_ATOF ("0.0"); ! 107: return tem; ! 108: } ! 109: } ! 110: ! 111: /* The result of this is always supposed to be a newly created tree node ! 112: not in use in any existing structure. */ ! 113: ! 114: static tree ! 115: convert_to_integer (type, expr) ! 116: tree type, expr; ! 117: { ! 118: register tree intype = TREE_TYPE (expr); ! 119: register enum tree_code form = TREE_CODE (intype); ! 120: ! 121: if (form == POINTER_TYPE) ! 122: { ! 123: if (integer_zerop (expr)) ! 124: expr = integer_zero_node; ! 125: else ! 126: expr = fold (build1 (CONVERT_EXPR, ! 127: type_for_size (POINTER_SIZE, 0), expr)); ! 128: intype = TREE_TYPE (expr); ! 129: form = TREE_CODE (intype); ! 130: if (intype == type) ! 131: return expr; ! 132: } ! 133: ! 134: if (form == INTEGER_TYPE || form == ENUMERAL_TYPE) ! 135: { ! 136: register unsigned outprec = TYPE_PRECISION (type); ! 137: register unsigned inprec = TYPE_PRECISION (intype); ! 138: register enum tree_code ex_form = TREE_CODE (expr); ! 139: ! 140: if (outprec >= inprec) ! 141: return build1 (NOP_EXPR, type, expr); ! 142: ! 143: /* Here detect when we can distribute the truncation down past some arithmetic. ! 144: For example, if adding two longs and converting to an int, ! 145: we can equally well convert both to ints and then add. ! 146: For the operations handled here, such truncation distribution ! 147: is always safe. ! 148: It is desirable in these cases: ! 149: 1) when truncating down to full-word from a larger size ! 150: 2) when truncating takes no work. ! 151: 3) when at least one operand of the arithmetic has been extended ! 152: (as by C's default conversions). In this case we need two conversions ! 153: if we do the arithmetic as already requested, so we might as well ! 154: truncate both and then combine. Perhaps that way we need only one. ! 155: ! 156: Note that in general we cannot do the arithmetic in a type ! 157: shorter than the desired result of conversion, even if the operands ! 158: are both extended from a shorter type, because they might overflow ! 159: if combined in that type. The exceptions to this--the times when ! 160: two narrow values can be combined in their narrow type even to ! 161: make a wider result--are handled by "shorten" in build_binary_op. */ ! 162: ! 163: switch (ex_form) ! 164: { ! 165: case RSHIFT_EXPR: ! 166: /* We can pass truncation down through right shifting ! 167: when the shift count is a negative constant. */ ! 168: if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST ! 169: || TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)) > 0) ! 170: break; ! 171: goto trunc1; ! 172: ! 173: case LSHIFT_EXPR: ! 174: /* We can pass truncation down through left shifting ! 175: when the shift count is a positive constant. */ ! 176: if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST ! 177: || TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)) < 0) ! 178: break; ! 179: /* In this case, shifting is like multiplication. */ ! 180: goto trunc1; ! 181: ! 182: case MAX_EXPR: ! 183: case MIN_EXPR: ! 184: case MULT_EXPR: ! 185: { ! 186: tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type); ! 187: tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type); ! 188: ! 189: /* Don't distribute unless the output precision is at least as big ! 190: as the actual inputs. Otherwise, the comparison of the ! 191: truncated values will be wrong. */ ! 192: if (outprec >= TYPE_PRECISION (TREE_TYPE (arg0)) ! 193: && outprec >= TYPE_PRECISION (TREE_TYPE (arg1)) ! 194: /* If signedness of arg0 and arg1 don't match, ! 195: we can't necessarily find a type to compare them in. */ ! 196: && (TREE_UNSIGNED (TREE_TYPE (arg0)) ! 197: == TREE_UNSIGNED (TREE_TYPE (arg1)))) ! 198: goto trunc1; ! 199: break; ! 200: } ! 201: ! 202: case PLUS_EXPR: ! 203: case MINUS_EXPR: ! 204: case BIT_AND_EXPR: ! 205: case BIT_IOR_EXPR: ! 206: case BIT_XOR_EXPR: ! 207: case BIT_ANDTC_EXPR: ! 208: trunc1: ! 209: { ! 210: tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type); ! 211: tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type); ! 212: ! 213: if (outprec >= BITS_PER_WORD ! 214: || TRULY_NOOP_TRUNCATION (outprec, inprec) ! 215: || inprec > TYPE_PRECISION (TREE_TYPE (arg0)) ! 216: || inprec > TYPE_PRECISION (TREE_TYPE (arg1))) ! 217: { ! 218: /* Do the arithmetic in type TYPEX, ! 219: then convert result to TYPE. */ ! 220: register tree typex = type; ! 221: ! 222: /* Can't do arithmetic in enumeral types ! 223: so use an integer type that will hold the values. */ ! 224: if (TREE_CODE (typex) == ENUMERAL_TYPE) ! 225: typex = type_for_size (TYPE_PRECISION (typex), ! 226: TREE_UNSIGNED (typex)); ! 227: ! 228: /* But now perhaps TYPEX is as wide as INPREC. ! 229: In that case, do nothing special here. ! 230: (Otherwise would recurse infinitely in convert. */ ! 231: if (TYPE_PRECISION (typex) != inprec) ! 232: { ! 233: /* Don't do unsigned arithmetic where signed was wanted, ! 234: or vice versa. ! 235: Exception: if either of the original operands were ! 236: unsigned then can safely do the work as unsigned. ! 237: And we may need to do it as unsigned ! 238: if we truncate to the original size. */ ! 239: typex = ((TREE_UNSIGNED (TREE_TYPE (expr)) ! 240: || TREE_UNSIGNED (TREE_TYPE (arg0)) ! 241: || TREE_UNSIGNED (TREE_TYPE (arg1))) ! 242: ? unsigned_type (typex) : signed_type (typex)); ! 243: return convert (type, ! 244: build_binary_op (ex_form, ! 245: convert (typex, arg0), ! 246: convert (typex, arg1), ! 247: 0)); ! 248: } ! 249: } ! 250: } ! 251: break; ! 252: ! 253: case EQ_EXPR: ! 254: case NE_EXPR: ! 255: case GT_EXPR: ! 256: case GE_EXPR: ! 257: case LT_EXPR: ! 258: case LE_EXPR: ! 259: case TRUTH_AND_EXPR: ! 260: case TRUTH_ANDIF_EXPR: ! 261: case TRUTH_OR_EXPR: ! 262: case TRUTH_ORIF_EXPR: ! 263: case TRUTH_NOT_EXPR: ! 264: /* If we want result of comparison converted to a byte, ! 265: we can just regard it as a byte, since it is 0 or 1. */ ! 266: TREE_TYPE (expr) = type; ! 267: return expr; ! 268: ! 269: case NEGATE_EXPR: ! 270: case BIT_NOT_EXPR: ! 271: case ABS_EXPR: ! 272: { ! 273: register tree typex = type; ! 274: ! 275: /* Can't do arithmetic in enumeral types ! 276: so use an integer type that will hold the values. */ ! 277: if (TREE_CODE (typex) == ENUMERAL_TYPE) ! 278: typex = type_for_size (TYPE_PRECISION (typex), ! 279: TREE_UNSIGNED (typex)); ! 280: ! 281: /* But now perhaps TYPEX is as wide as INPREC. ! 282: In that case, do nothing special here. ! 283: (Otherwise would recurse infinitely in convert. */ ! 284: if (TYPE_PRECISION (typex) != inprec) ! 285: { ! 286: /* Don't do unsigned arithmetic where signed was wanted, ! 287: or vice versa. */ ! 288: typex = (TREE_UNSIGNED (TREE_TYPE (expr)) ! 289: ? unsigned_type (typex) : signed_type (typex)); ! 290: return convert (type, ! 291: build_unary_op (ex_form, ! 292: convert (typex, TREE_OPERAND (expr, 0)), ! 293: 1)); ! 294: } ! 295: } ! 296: ! 297: case NOP_EXPR: ! 298: /* If truncating after truncating, might as well do all at once. ! 299: If truncating after extending, we may get rid of wasted work. */ ! 300: return convert (type, get_unwidened (TREE_OPERAND (expr, 0), type)); ! 301: ! 302: case COND_EXPR: ! 303: /* Can treat the two alternative values like the operands ! 304: of an arithmetic expression. */ ! 305: { ! 306: tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type); ! 307: tree arg2 = get_unwidened (TREE_OPERAND (expr, 2), type); ! 308: ! 309: if (outprec >= BITS_PER_WORD ! 310: || TRULY_NOOP_TRUNCATION (outprec, inprec) ! 311: || inprec > TYPE_PRECISION (TREE_TYPE (arg1)) ! 312: || inprec > TYPE_PRECISION (TREE_TYPE (arg2))) ! 313: { ! 314: /* Do the arithmetic in type TYPEX, ! 315: then convert result to TYPE. */ ! 316: register tree typex = type; ! 317: ! 318: /* Can't do arithmetic in enumeral types ! 319: so use an integer type that will hold the values. */ ! 320: if (TREE_CODE (typex) == ENUMERAL_TYPE) ! 321: typex = type_for_size (TYPE_PRECISION (typex), ! 322: TREE_UNSIGNED (typex)); ! 323: ! 324: /* But now perhaps TYPEX is as wide as INPREC. ! 325: In that case, do nothing special here. ! 326: (Otherwise would recurse infinitely in convert. */ ! 327: if (TYPE_PRECISION (typex) != inprec) ! 328: { ! 329: /* Don't do unsigned arithmetic where signed was wanted, ! 330: or vice versa. */ ! 331: typex = (TREE_UNSIGNED (TREE_TYPE (expr)) ! 332: ? unsigned_type (typex) : signed_type (typex)); ! 333: return convert (type, ! 334: fold (build (COND_EXPR, typex, ! 335: TREE_OPERAND (expr, 0), ! 336: convert (typex, arg1), ! 337: convert (typex, arg2)))); ! 338: } ! 339: } ! 340: } ! 341: } ! 342: ! 343: return build1 (NOP_EXPR, type, expr); ! 344: } ! 345: ! 346: if (form == REAL_TYPE) ! 347: return build1 (FIX_TRUNC_EXPR, type, expr); ! 348: ! 349: error ("aggregate value used where an integer was expected"); ! 350: ! 351: { ! 352: register tree tem = build_int_2 (0, 0); ! 353: TREE_TYPE (tem) = type; ! 354: return tem; ! 355: } ! 356: } ! 357: ! 358: /* Create an expression whose value is that of EXPR, ! 359: converted to type TYPE. The TREE_TYPE of the value ! 360: is always TYPE. This function implements all reasonable ! 361: conversions; callers should filter out those that are ! 362: not permitted by the language being compiled. */ ! 363: ! 364: tree ! 365: convert (type, expr) ! 366: tree type, expr; ! 367: { ! 368: register tree e = expr; ! 369: register enum tree_code code = TREE_CODE (type); ! 370: ! 371: if (type == TREE_TYPE (expr) || TREE_CODE (expr) == ERROR_MARK) ! 372: return expr; ! 373: if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) ! 374: return error_mark_node; ! 375: if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE) ! 376: { ! 377: error ("void value not ignored as it ought to be"); ! 378: return error_mark_node; ! 379: } ! 380: if (code == VOID_TYPE) ! 381: return build1 (CONVERT_EXPR, type, e); ! 382: #if 0 ! 383: /* This is incorrect. A truncation can't be stripped this way. ! 384: Extensions will be stripped by the use of get_unwidened. */ ! 385: if (TREE_CODE (expr) == NOP_EXPR) ! 386: return convert (type, TREE_OPERAND (expr, 0)); ! 387: #endif ! 388: if (code == INTEGER_TYPE || code == ENUMERAL_TYPE) ! 389: return fold (convert_to_integer (type, e)); ! 390: if (code == POINTER_TYPE) ! 391: return fold (convert_to_pointer (type, e)); ! 392: if (code == REAL_TYPE) ! 393: return fold (convert_to_real (type, e)); ! 394: ! 395: error ("conversion to non-scalar type requested"); ! 396: return error_mark_node; ! 397: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.