@@ -1103,21 +1103,34 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
1103
1103
1104
1104
fn store_with_flags (
1105
1105
& mut self ,
1106
- val : RValue < ' gcc > ,
1106
+ mut val : RValue < ' gcc > ,
1107
1107
ptr : RValue < ' gcc > ,
1108
1108
align : Align ,
1109
- _flags : MemFlags ,
1109
+ flags : MemFlags ,
1110
1110
) -> RValue < ' gcc > {
1111
1111
let ptr = self . check_store ( val, ptr) ;
1112
1112
let destination = ptr. dereference ( self . location ) ;
1113
1113
// NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast
1114
1114
// to type so it gets the proper alignment.
1115
1115
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 = self . cx . context . new_bitcast ( None , ptr, modified_destination_type. make_pointer ( ) ) ;
1131
+ let modified_destination = modified_ptr. dereference ( None ) ;
1132
+ self . llbb ( ) . add_assignment ( None , modified_destination, val) ;
1133
+ // TODO: handle `MemFlags::NONTEMPORAL`.
1121
1134
// NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
1122
1135
self . cx . context . new_rvalue_zero ( self . type_i32 ( ) )
1123
1136
}
0 commit comments