@@ -226,8 +226,10 @@ pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
226226pub struct AddressSpaceInfo {
227227 /// The size of the bitwise representation of the pointer.
228228 pointer_size : Size ,
229- /// The alignment requirements for pointers in this address space.
229+ /// The ABI alignment requirements for pointers in this address space.
230230 pointer_align : AbiAlign ,
231+ /// The preferred alignment specification for pointers in this address space.
232+ pointer_preferred_align : AbiAlign ,
231233 /// The size of the index that used for address calculations on pointers in this address space.
232234 pointer_index : Size ,
233235}
@@ -296,6 +298,7 @@ impl Default for TargetDataLayout {
296298 default_address_space_info : AddressSpaceInfo {
297299 pointer_size : Size :: from_bits ( 64 ) ,
298300 pointer_align : AbiAlign :: new ( align ( 64 ) ) ,
301+ pointer_preferred_align : AbiAlign :: new ( align ( 64 ) ) ,
299302 pointer_index : Size :: from_bits ( 64 ) ,
300303 } ,
301304 address_space_info : vec ! [ ] ,
@@ -313,6 +316,7 @@ pub enum TargetDataLayoutErrors<'a> {
313316 InconsistentTargetArchitecture { dl : & ' a str , target : & ' a str } ,
314317 InconsistentTargetPointerWidth { pointer_size : u64 , target : u32 } ,
315318 InvalidBitsSize { err : String } ,
319+ UnknownPointerSpecification { err : String } ,
316320}
317321
318322impl TargetDataLayout {
@@ -347,18 +351,24 @@ impl TargetDataLayout {
347351 |s : & ' a str , cause : & ' a str | parse_bits ( s, "size" , cause) . map ( Size :: from_bits) ;
348352
349353 // Parse an alignment string.
350- let parse_align = |s : & [ & ' a str ] , cause : & ' a str | {
351- if s. is_empty ( ) {
352- return Err ( TargetDataLayoutErrors :: MissingAlignment { cause } ) ;
353- }
354+ let parse_align_str = |s : & ' a str , cause : & ' a str | {
354355 let align_from_bits = |bits| {
355356 Align :: from_bits ( bits)
356357 . map_err ( |err| TargetDataLayoutErrors :: InvalidAlignment { cause, err } )
357358 } ;
358- let abi = parse_bits ( s[ 0 ] , "alignment" , cause) ?;
359+ let abi = parse_bits ( s, "alignment" , cause) ?;
359360 Ok ( AbiAlign :: new ( align_from_bits ( abi) ?) )
360361 } ;
361362
363+ // Parse an alignment sequence, possibly in the form `<align>[:<preferred_alignment>]`,
364+ // ignoring the secondary alignment specifications.
365+ let parse_align_seq = |s : & [ & ' a str ] , cause : & ' a str | {
366+ if s. is_empty ( ) {
367+ return Err ( TargetDataLayoutErrors :: MissingAlignment { cause } ) ;
368+ }
369+ parse_align_str ( s[ 0 ] , cause)
370+ } ;
371+
362372 let mut dl = TargetDataLayout :: default ( ) ;
363373 dl. default_address_space = default_address_space;
364374
@@ -372,27 +382,37 @@ impl TargetDataLayout {
372382 [ p] if p. starts_with ( 'P' ) => {
373383 dl. instruction_address_space = parse_address_space ( & p[ 1 ..] , "P" ) ?
374384 }
375- [ "a" , a @ ..] => dl. aggregate_align = parse_align ( a, "a" ) ?,
376- [ "f16" , a @ ..] => dl. f16_align = parse_align ( a, "f16" ) ?,
377- [ "f32" , a @ ..] => dl. f32_align = parse_align ( a, "f32" ) ?,
378- [ "f64" , a @ ..] => dl. f64_align = parse_align ( a, "f64" ) ?,
379- [ "f128" , a @ ..] => dl. f128_align = parse_align ( a, "f128" ) ?,
385+ [ "a" , a @ ..] => dl. aggregate_align = parse_align_seq ( a, "a" ) ?,
386+ [ "f16" , a @ ..] => dl. f16_align = parse_align_seq ( a, "f16" ) ?,
387+ [ "f32" , a @ ..] => dl. f32_align = parse_align_seq ( a, "f32" ) ?,
388+ [ "f64" , a @ ..] => dl. f64_align = parse_align_seq ( a, "f64" ) ?,
389+ [ "f128" , a @ ..] => dl. f128_align = parse_align_seq ( a, "f128" ) ?,
380390 [ p, s, a @ ..] if p. starts_with ( "p" ) => {
391+ let p = p. strip_prefix ( 'p' ) . unwrap ( ) ;
392+
381393 // Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
382394 // they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
383- let p = p. trim_start_matches ( char:: is_alphabetic) ;
395+ // However, we currently don't take into account those further specifications:
396+ // an error is emitted instead.
397+ if p. starts_with ( char:: is_alphabetic) {
398+ return Err ( TargetDataLayoutErrors :: UnknownPointerSpecification {
399+ err : p. to_string ( ) ,
400+ } ) ;
401+ }
384402
385403 let addr_space = if !p. is_empty ( ) {
386- parse_address_space ( p, "p" ) ?
404+ parse_address_space ( p, "p- " ) ?
387405 } else {
388406 AddressSpace :: ZERO
389407 } ;
390408
391- let pointer_size = parse_size ( s, p) ?;
409+ let pointer_size = parse_size ( s, "p-" ) ?;
410+ let pointer_align = parse_align_seq ( a, "p-" ) ?;
392411 let info = AddressSpaceInfo {
393412 pointer_index : pointer_size,
394413 pointer_size,
395- pointer_align : parse_align ( a, p) ?,
414+ pointer_preferred_align : pointer_align,
415+ pointer_align,
396416 } ;
397417 if addr_space == default_address_space {
398418 dl. default_address_space_info = info;
@@ -405,10 +425,18 @@ impl TargetDataLayout {
405425 }
406426 }
407427 }
408- [ p, s, _pr, i, a @ ..] if p. starts_with ( "p" ) => {
428+ [ p, s, a, pr, i] if p. starts_with ( "p" ) => {
429+ let p = p. strip_prefix ( 'p' ) . unwrap ( ) ;
430+
409431 // Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
410432 // they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
411- let p = p. trim_start_matches ( char:: is_alphabetic) ;
433+ // However, we currently don't take into account those further specifications:
434+ // an error is emitted instead.
435+ if p. starts_with ( char:: is_alphabetic) {
436+ return Err ( TargetDataLayoutErrors :: UnknownPointerSpecification {
437+ err : p. to_string ( ) ,
438+ } ) ;
439+ }
412440
413441 let addr_space = if !p. is_empty ( ) {
414442 parse_address_space ( p, "p" ) ?
@@ -417,9 +445,10 @@ impl TargetDataLayout {
417445 } ;
418446
419447 let info = AddressSpaceInfo {
420- pointer_align : parse_align ( a, p) ?,
421- pointer_size : parse_size ( s, p) ?,
422- pointer_index : parse_size ( i, p) ?,
448+ pointer_size : parse_size ( s, "p-" ) ?,
449+ pointer_align : parse_align_str ( a, "p-" ) ?,
450+ pointer_preferred_align : parse_align_str ( pr, "p-" ) ?,
451+ pointer_index : parse_size ( i, "p-" ) ?,
423452 } ;
424453
425454 if addr_space == default_address_space {
@@ -439,7 +468,7 @@ impl TargetDataLayout {
439468 parse_size ( & s[ 1 ..] , "i" ) ?; // For the user error.
440469 continue ;
441470 } ;
442- let a = parse_align ( a, s) ?;
471+ let a = parse_align_seq ( a, s) ?;
443472 match bits {
444473 1 => dl. i1_align = a,
445474 8 => dl. i8_align = a,
@@ -457,7 +486,7 @@ impl TargetDataLayout {
457486 }
458487 [ s, a @ ..] if s. starts_with ( 'v' ) => {
459488 let v_size = parse_size ( & s[ 1 ..] , "v" ) ?;
460- let a = parse_align ( a, s) ?;
489+ let a = parse_align_seq ( a, s) ?;
461490 if let Some ( v) = dl. vector_align . iter_mut ( ) . find ( |v| v. 0 == v_size) {
462491 v. 1 = a;
463492 continue ;
@@ -622,6 +651,26 @@ impl TargetDataLayout {
622651 panic ! ( "Use of unknown address space {c:?}" ) ;
623652 }
624653 }
654+
655+ /// Get the preferred pointer alignment in the default data address space.
656+ #[ inline]
657+ pub fn pointer_preferred_align ( & self ) -> AbiAlign {
658+ self . default_address_space_info . pointer_preferred_align
659+ }
660+
661+ /// Get the preferred pointer alignment in a specific address space.
662+ #[ inline]
663+ pub fn pointer_preferred_align_in ( & self , c : AddressSpace ) -> AbiAlign {
664+ if c == self . default_address_space {
665+ return self . default_address_space_info . pointer_preferred_align ;
666+ }
667+
668+ if let Some ( e) = self . address_space_info . iter ( ) . find ( |( a, _) | a == & c) {
669+ e. 1 . pointer_preferred_align
670+ } else {
671+ panic ! ( "Use of unknown address space {c:?}" ) ;
672+ }
673+ }
625674}
626675
627676pub trait HasDataLayout {
0 commit comments