@@ -520,8 +520,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
520
520
self . block
521
521
}
522
522
523
- fn append_block ( cx : & ' a CodegenCx < ' gcc , ' tcx > , func : RValue < ' gcc > , name : & str ) -> Block < ' gcc > {
524
- let func = cx. rvalue_as_function ( func) ;
523
+ fn append_block ( _: & ' a CodegenCx < ' gcc , ' tcx > , func : Function < ' gcc > , name : & str ) -> Block < ' gcc > {
525
524
func. new_block ( name)
526
525
}
527
526
@@ -782,6 +781,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
782
781
return self . context . new_call ( self . location , fmod, & [ a, b] ) ;
783
782
}
784
783
TypeKind :: FP128 => {
784
+ // TODO(antoyo): use get_simple_function_f128_2args.
785
785
let f128_type = self . type_f128 ( ) ;
786
786
let fmodf128 = self . context . new_function (
787
787
None ,
@@ -938,22 +938,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
938
938
fn load ( & mut self , pointee_ty : Type < ' gcc > , ptr : RValue < ' gcc > , align : Align ) -> RValue < ' gcc > {
939
939
let block = self . llbb ( ) ;
940
940
let function = block. get_function ( ) ;
941
+ // NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned.
942
+ // For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned)
943
+ // Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked"
944
+ //
945
+ // From GCCs perspective:
946
+ // __int128_t __attribute__((aligned(16))) __attribute__((aligned(16)))
947
+ // and:
948
+ // __int128_t __attribute__((aligned(16)))
949
+ // are 2 distinct, incompatible types.
950
+ //
951
+ // So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types,
952
+ // but the GCC APIs to facilitate this just aren't quite there yet.
953
+
954
+ // This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment.
955
+ // Otherwise, this may be an under-aligned load, so we will still call get_aligned.
956
+ let mut can_skip_align = ( pointee_ty == self . cx . u128_type
957
+ || pointee_ty == self . cx . i128_type )
958
+ && align == self . int128_align ;
959
+ // We can skip the call to `get_aligned` for byte-sized types with alignment of 1.
960
+ can_skip_align = can_skip_align
961
+ || ( pointee_ty == self . cx . u8_type || pointee_ty == self . cx . i8_type )
962
+ && align. bytes ( ) == 1 ;
963
+ // Skip the call to `get_aligned` when possible.
964
+ let aligned_type =
965
+ if can_skip_align { pointee_ty } else { pointee_ty. get_aligned ( align. bytes ( ) ) } ;
966
+
967
+ let ptr = self . context . new_cast ( self . location , ptr, aligned_type. make_pointer ( ) ) ;
941
968
// NOTE: instead of returning the dereference here, we have to assign it to a variable in
942
969
// the current basic block. Otherwise, it could be used in another basic block, causing a
943
970
// dereference after a drop, for instance.
944
- // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
945
- // Ideally, we shouldn't need to do this check.
946
- // FractalFir: the `align == self.int128_align` check ensures we *do* call `get_aligned` if
947
- // the alignment of a `u128`/`i128` is not the one mandated by the ABI. This ensures we handle
948
- // under-aligned loads correctly.
949
- let aligned_type = if ( pointee_ty == self . cx . u128_type || pointee_ty == self . cx . i128_type )
950
- && align == self . int128_align
951
- {
952
- pointee_ty
953
- } else {
954
- pointee_ty. get_aligned ( align. bytes ( ) )
955
- } ;
956
- let ptr = self . context . new_cast ( self . location , ptr, aligned_type. make_pointer ( ) ) ;
957
971
let deref = ptr. dereference ( self . location ) . to_rvalue ( ) ;
958
972
let loaded_value = function. new_local (
959
973
self . location ,
@@ -1105,7 +1119,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
1105
1119
// TODO(antoyo)
1106
1120
}
1107
1121
1108
- fn store ( & mut self , val : RValue < ' gcc > , ptr : RValue < ' gcc > , align : Align ) -> RValue < ' gcc > {
1122
+ fn store ( & mut self , mut val : RValue < ' gcc > , ptr : RValue < ' gcc > , align : Align ) -> RValue < ' gcc > {
1123
+ if self . structs_as_pointer . borrow ( ) . contains ( & val) {
1124
+ // NOTE: hack to workaround a limitation of the rustc API: see comment on
1125
+ // CodegenCx.structs_as_pointer
1126
+ val = val. dereference ( self . location ) . to_rvalue ( ) ;
1127
+ }
1128
+
1109
1129
self . store_with_flags ( val, ptr, align, MemFlags :: empty ( ) )
1110
1130
}
1111
1131
@@ -1551,16 +1571,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
1551
1571
aggregate_value
1552
1572
}
1553
1573
1554
- fn set_personality_fn ( & mut self , _personality : RValue < ' gcc > ) {
1574
+ fn set_personality_fn ( & mut self , _personality : Function < ' gcc > ) {
1555
1575
#[ cfg( feature = "master" ) ]
1556
- {
1557
- let personality = self . rvalue_as_function ( _personality) ;
1558
- self . current_func ( ) . set_personality_function ( personality) ;
1559
- }
1576
+ self . current_func ( ) . set_personality_function ( _personality) ;
1560
1577
}
1561
1578
1562
1579
#[ cfg( feature = "master" ) ]
1563
- fn cleanup_landing_pad ( & mut self , pers_fn : RValue < ' gcc > ) -> ( RValue < ' gcc > , RValue < ' gcc > ) {
1580
+ fn cleanup_landing_pad ( & mut self , pers_fn : Function < ' gcc > ) -> ( RValue < ' gcc > , RValue < ' gcc > ) {
1564
1581
self . set_personality_fn ( pers_fn) ;
1565
1582
1566
1583
// NOTE: insert the current block in a variable so that a later call to invoke knows to
@@ -1581,7 +1598,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
1581
1598
}
1582
1599
1583
1600
#[ cfg( not( feature = "master" ) ) ]
1584
- fn cleanup_landing_pad ( & mut self , _pers_fn : RValue < ' gcc > ) -> ( RValue < ' gcc > , RValue < ' gcc > ) {
1601
+ fn cleanup_landing_pad ( & mut self , _pers_fn : Function < ' gcc > ) -> ( RValue < ' gcc > , RValue < ' gcc > ) {
1585
1602
let value1 = self
1586
1603
. current_func ( )
1587
1604
. new_local ( self . location , self . u8_type . make_pointer ( ) , "landing_pad0" )
@@ -1591,7 +1608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
1591
1608
( value1, value2)
1592
1609
}
1593
1610
1594
- fn filter_landing_pad ( & mut self , pers_fn : RValue < ' gcc > ) {
1611
+ fn filter_landing_pad ( & mut self , pers_fn : Function < ' gcc > ) {
1595
1612
// TODO(antoyo): generate the correct landing pad
1596
1613
self . cleanup_landing_pad ( pers_fn) ;
1597
1614
}
0 commit comments