Skip to content

Commit a2fc993

Browse files
committed
[squash me] compiler: error out on unknown pointer specifications + parse preferred alignment spec in p-
1 parent 948d4d6 commit a2fc993

File tree

4 files changed

+79
-22
lines changed

4 files changed

+79
-22
lines changed

compiler/rustc_abi/src/lib.rs

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,10 @@ pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
226226
pub 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

318322
impl 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

627676
pub trait HasDataLayout {

compiler/rustc_errors/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,8 @@ errors_target_invalid_bits =
4141
4242
errors_target_invalid_bits_size = {$err}
4343
44+
errors_target_invalid_datalayout_pointer_spec =
45+
unknown pointer specification `{$err}` in datalayout string
46+
4447
errors_target_missing_alignment =
4548
missing alignment for `{$cause}` in "data-layout"

compiler/rustc_errors/src/diagnostic_impls.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
374374
TargetDataLayoutErrors::InvalidBitsSize { err } => {
375375
Diag::new(dcx, level, fluent::errors_target_invalid_bits_size).with_arg("err", err)
376376
}
377+
TargetDataLayoutErrors::UnknownPointerSpecification { err } => {
378+
Diag::new(dcx, level, fluent::errors_target_invalid_datalayout_pointer_spec)
379+
.with_arg("err", err)
380+
}
377381
}
378382
}
379383
}

src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub fn target_data_layout_query(
3939
target,
4040
} => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#),
4141
TargetDataLayoutErrors::InvalidBitsSize { err } => err,
42+
TargetDataLayoutErrors::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifer in "data-layout": {err}"#),
4243
}.into())
4344
}
4445
},

0 commit comments

Comments
 (0)