@@ -226,8 +226,10 @@ pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
226
226
pub struct AddressSpaceInfo {
227
227
/// The size of the bitwise representation of the pointer.
228
228
pointer_size : Size ,
229
- /// The alignment requirements for pointers in this address space.
229
+ /// The ABI alignment requirements for pointers in this address space.
230
230
pointer_align : AbiAlign ,
231
+ /// The preferred alignment specification for pointers in this address space.
232
+ pointer_preferred_align : AbiAlign ,
231
233
/// The size of the index that used for address calculations on pointers in this address space.
232
234
pointer_index : Size ,
233
235
}
@@ -296,6 +298,7 @@ impl Default for TargetDataLayout {
296
298
default_address_space_info : AddressSpaceInfo {
297
299
pointer_size : Size :: from_bits ( 64 ) ,
298
300
pointer_align : AbiAlign :: new ( align ( 64 ) ) ,
301
+ pointer_preferred_align : AbiAlign :: new ( align ( 64 ) ) ,
299
302
pointer_index : Size :: from_bits ( 64 ) ,
300
303
} ,
301
304
address_space_info : vec ! [ ] ,
@@ -313,6 +316,7 @@ pub enum TargetDataLayoutErrors<'a> {
313
316
InconsistentTargetArchitecture { dl : & ' a str , target : & ' a str } ,
314
317
InconsistentTargetPointerWidth { pointer_size : u64 , target : u32 } ,
315
318
InvalidBitsSize { err : String } ,
319
+ UnknownPointerSpecification { err : String } ,
316
320
}
317
321
318
322
impl TargetDataLayout {
@@ -347,18 +351,24 @@ impl TargetDataLayout {
347
351
|s : & ' a str , cause : & ' a str | parse_bits ( s, "size" , cause) . map ( Size :: from_bits) ;
348
352
349
353
// 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 | {
354
355
let align_from_bits = |bits| {
355
356
Align :: from_bits ( bits)
356
357
. map_err ( |err| TargetDataLayoutErrors :: InvalidAlignment { cause, err } )
357
358
} ;
358
- let abi = parse_bits ( s[ 0 ] , "alignment" , cause) ?;
359
+ let abi = parse_bits ( s, "alignment" , cause) ?;
359
360
Ok ( AbiAlign :: new ( align_from_bits ( abi) ?) )
360
361
} ;
361
362
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
+
362
372
let mut dl = TargetDataLayout :: default ( ) ;
363
373
dl. default_address_space = default_address_space;
364
374
@@ -372,27 +382,37 @@ impl TargetDataLayout {
372
382
[ p] if p. starts_with ( 'P' ) => {
373
383
dl. instruction_address_space = parse_address_space ( & p[ 1 ..] , "P" ) ?
374
384
}
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" ) ?,
380
390
[ p, s, a @ ..] if p. starts_with ( "p" ) => {
391
+ let p = p. strip_prefix ( 'p' ) . unwrap ( ) ;
392
+
381
393
// Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
382
394
// 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
+ }
384
402
385
403
let addr_space = if !p. is_empty ( ) {
386
- parse_address_space ( p, "p" ) ?
404
+ parse_address_space ( p, "p- " ) ?
387
405
} else {
388
406
AddressSpace :: ZERO
389
407
} ;
390
408
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-" ) ?;
392
411
let info = AddressSpaceInfo {
393
412
pointer_index : pointer_size,
394
413
pointer_size,
395
- pointer_align : parse_align ( a, p) ?,
414
+ pointer_preferred_align : pointer_align,
415
+ pointer_align,
396
416
} ;
397
417
if addr_space == default_address_space {
398
418
dl. default_address_space_info = info;
@@ -405,10 +425,18 @@ impl TargetDataLayout {
405
425
}
406
426
}
407
427
}
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
+
409
431
// Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
410
432
// 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
+ }
412
440
413
441
let addr_space = if !p. is_empty ( ) {
414
442
parse_address_space ( p, "p" ) ?
@@ -417,9 +445,10 @@ impl TargetDataLayout {
417
445
} ;
418
446
419
447
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-" ) ?,
423
452
} ;
424
453
425
454
if addr_space == default_address_space {
@@ -439,7 +468,7 @@ impl TargetDataLayout {
439
468
parse_size ( & s[ 1 ..] , "i" ) ?; // For the user error.
440
469
continue ;
441
470
} ;
442
- let a = parse_align ( a, s) ?;
471
+ let a = parse_align_seq ( a, s) ?;
443
472
match bits {
444
473
1 => dl. i1_align = a,
445
474
8 => dl. i8_align = a,
@@ -457,7 +486,7 @@ impl TargetDataLayout {
457
486
}
458
487
[ s, a @ ..] if s. starts_with ( 'v' ) => {
459
488
let v_size = parse_size ( & s[ 1 ..] , "v" ) ?;
460
- let a = parse_align ( a, s) ?;
489
+ let a = parse_align_seq ( a, s) ?;
461
490
if let Some ( v) = dl. vector_align . iter_mut ( ) . find ( |v| v. 0 == v_size) {
462
491
v. 1 = a;
463
492
continue ;
@@ -622,6 +651,26 @@ impl TargetDataLayout {
622
651
panic ! ( "Use of unknown address space {c:?}" ) ;
623
652
}
624
653
}
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
+ }
625
674
}
626
675
627
676
pub trait HasDataLayout {
0 commit comments