GCCのバグを直した
GCCで8bit長・16bit長のビットフィールドが正しく扱われない(STRICT_ALGINMENTな環境でもアライン無視する、volatile付けると領域破壊を起こす)問題を修正した。
BTSには投げたけれど、多分無視されるのでここにパッチを置いておく(gcc-4_6-branch/trunkにて動作確認)。
I fixed the problem around handling bit-field (GCC generates wrong code when using 8bit or 16bit width of bit-field.)
Patch is here (also posted to BTS.)
diff --git a/gcc/expr.c b/gcc/expr.c index a4cfee0..a2823a2 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4689,7 +4689,7 @@ expand_assignment (tree to, tree from, bool nontemporal) use BLKmode for it instead. */ if (MEM_P (to_rtx)) { - if (volatilep && flag_strict_volatile_bitfields > 0) + if (STRICT_ALIGNMENT || (volatilep && flag_strict_volatile_bitfields > 0)) to_rtx = adjust_address (to_rtx, mode1, 0); else if (GET_MODE (to_rtx) == VOIDmode) to_rtx = adjust_address (to_rtx, BLKmode, 0); @@ -6345,7 +6345,9 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, store it as a bit field. */ || (mode != BLKmode && ((((MEM_ALIGN (target) < GET_MODE_ALIGNMENT (mode)) - || bitpos % GET_MODE_ALIGNMENT (mode)) + || bitpos % GET_MODE_ALIGNMENT (mode) + || (TREE_THIS_VOLATILE (type) + && flag_strict_volatile_bitfields > 0)) && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target))) || (bitpos % BITS_PER_UNIT != 0))) /* If the RHS and field are a constant size and the size of the @@ -6510,8 +6512,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, mode = DECL_MODE (field); else if (DECL_MODE (field) == BLKmode) blkmode_bitfield = true; - else if (TREE_THIS_VOLATILE (exp) - && flag_strict_volatile_bitfields > 0) + else if (STRICT_ALIGNMENT || (TREE_THIS_VOLATILE (exp) + && flag_strict_volatile_bitfields > 0)) /* Volatile bitfields should be accessed in the mode of the field's type, not the mode computed based on the bit size. */ @@ -9624,7 +9626,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, use BLKmode for it instead. */ if (MEM_P (op0)) { - if (volatilep && flag_strict_volatile_bitfields > 0) + if (STRICT_ALIGNMENT || (volatilep && flag_strict_volatile_bitfields > 0)) op0 = adjust_address (op0, mode1, 0); else if (GET_MODE (op0) == VOIDmode) op0 = adjust_address (op0, BLKmode, 0); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 359541e..7ebba2f 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -626,6 +626,7 @@ layout_decl (tree decl, unsigned int known_align) if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT + && !STRICT_ALIGNMENT && !(TREE_THIS_VOLATILE (decl) && flag_strict_volatile_bitfields > 0)) {