-static tree
-sra_build_assignment (tree dst, tree src)
-{
- /* Turning BIT_FIELD_REFs into bit operations enables other passes
- to do a much better job at optimizing the code.
- From dst = BIT_FIELD_REF <var, sz, off> we produce
-
- SR.1 = (scalar type) var;
- SR.2 = SR.1 >> off;
- SR.3 = SR.2 & ((1 << sz) - 1);
- ... possible sign extension of SR.3 ...
- dst = (destination type) SR.3;
- */
- if (scalar_bitfield_p (src))
- {
- tree var, shift, width;
- tree utype, stype, stmp, utmp, dtmp;
- tree list, stmt;
- bool unsignedp = (INTEGRAL_TYPE_P (TREE_TYPE (src))
- ? TYPE_UNSIGNED (TREE_TYPE (src)) : true);
-
- var = TREE_OPERAND (src, 0);
- width = TREE_OPERAND (src, 1);
- /* The offset needs to be adjusted to a right shift quantity
- depending on the endianness. */
- if (BYTES_BIG_ENDIAN)
- {
- tree tmp = size_binop (PLUS_EXPR, width, TREE_OPERAND (src, 2));
- shift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), tmp);
- }
- else
- shift = TREE_OPERAND (src, 2);
-
- /* In weird cases we have non-integral types for the source or
- destination object.
- ??? For unknown reasons we also want an unsigned scalar type. */
- stype = TREE_TYPE (var);
- if (!INTEGRAL_TYPE_P (stype))
- stype = lang_hooks.types.type_for_size (TREE_INT_CST_LOW
- (TYPE_SIZE (stype)), 1);
- else if (!TYPE_UNSIGNED (stype))
- stype = unsigned_type_for (stype);
-
- utype = TREE_TYPE (dst);
- if (!INTEGRAL_TYPE_P (utype))
- utype = lang_hooks.types.type_for_size (TREE_INT_CST_LOW
- (TYPE_SIZE (utype)), 1);
- else if (!TYPE_UNSIGNED (utype))
- utype = unsigned_type_for (utype);
-
- list = NULL;
- stmp = make_rename_temp (stype, "SR");
-
- /* Convert the base var of the BIT_FIELD_REF to the scalar type
- we use for computation if we cannot use it directly. */
- if (!useless_type_conversion_p (stype, TREE_TYPE (var)))
- {
- if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
- stmt = build_gimple_modify_stmt (stmp,
- fold_convert (stype, var));
- else
- stmt = build_gimple_modify_stmt (stmp,
- fold_build1 (VIEW_CONVERT_EXPR,
- stype, var));
- append_to_statement_list (stmt, &list);
- var = stmp;
- }