@@ -1103,21 +1103,35 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
11031103
11041104 fn store_with_flags (
11051105 & mut self ,
1106- val : RValue < ' gcc > ,
1106+ mut val : RValue < ' gcc > ,
11071107 ptr : RValue < ' gcc > ,
11081108 align : Align ,
1109- _flags : MemFlags ,
1109+ flags : MemFlags ,
11101110 ) -> RValue < ' gcc > {
11111111 let ptr = self . check_store ( val, ptr) ;
11121112 let destination = ptr. dereference ( self . location ) ;
11131113 // NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast
11141114 // to type so it gets the proper alignment.
11151115 let destination_type = destination. to_rvalue ( ) . get_type ( ) . unqualified ( ) ;
1116- let aligned_type = destination_type. get_aligned ( align. bytes ( ) ) . make_pointer ( ) ;
1117- let aligned_destination = self . cx . context . new_bitcast ( self . location , ptr, aligned_type) ;
1118- let aligned_destination = aligned_destination. dereference ( self . location ) ;
1119- self . llbb ( ) . add_assignment ( self . location , aligned_destination, val) ;
1120- // TODO(antoyo): handle align and flags.
1116+ let align = if flags. contains ( MemFlags :: UNALIGNED ) { 1 } else { align. bytes ( ) } ;
1117+ let mut modified_destination_type = destination_type. get_aligned ( align) ;
1118+ if flags. contains ( MemFlags :: VOLATILE ) {
1119+ modified_destination_type = modified_destination_type. make_volatile ( ) ;
1120+ }
1121+
1122+ // FIXME: The type checking in `add_assignment` removes only one
1123+ // qualifier from each side. So the writes `int → volatile int` and
1124+ // `int → int __attribute__((aligned(1)))` are considered legal but
1125+ // `int → volatile int __attribute__((aligned(1)))` is not. This seems
1126+ // like a bug in libgccjit. The easiest way to work around this is to
1127+ // bitcast `val` to have the matching qualifiers.
1128+ val = self . cx . context . new_bitcast ( None , val, modified_destination_type) ;
1129+
1130+ let modified_ptr =
1131+ self . cx . context . new_bitcast ( None , ptr, modified_destination_type. make_pointer ( ) ) ;
1132+ let modified_destination = modified_ptr. dereference ( None ) ;
1133+ self . llbb ( ) . add_assignment ( None , modified_destination, val) ;
1134+ // TODO: handle `MemFlags::NONTEMPORAL`.
11211135 // NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
11221136 self . cx . context . new_rvalue_zero ( self . type_i32 ( ) )
11231137 }
0 commit comments