Skip to content

Commit

Permalink
Use the Align type when parsing alignment attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
beetrees committed Mar 24, 2024
1 parent 2f090c3 commit dc18eb5
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 24 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Expand Up @@ -3560,6 +3560,7 @@ dependencies = [
name = "rustc_attr"
version = "0.0.0"
dependencies = [
"rustc_abi",
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_abi/src/lib.rs
Expand Up @@ -698,6 +698,7 @@ impl fmt::Display for AlignFromBytesError {

impl Align {
pub const ONE: Align = Align { pow2: 0 };
pub const EIGHT: Align = Align { pow2: 3 };
// LLVM has a maximal supported alignment of 2^29, we inherit that.
pub const MAX: Align = Align { pow2: 29 };

Expand All @@ -707,19 +708,19 @@ impl Align {
}

#[inline]
pub fn from_bytes(align: u64) -> Result<Align, AlignFromBytesError> {
pub const fn from_bytes(align: u64) -> Result<Align, AlignFromBytesError> {
// Treat an alignment of 0 bytes like 1-byte alignment.
if align == 0 {
return Ok(Align::ONE);
}

#[cold]
fn not_power_of_2(align: u64) -> AlignFromBytesError {
const fn not_power_of_2(align: u64) -> AlignFromBytesError {
AlignFromBytesError::NotPowerOfTwo(align)
}

#[cold]
fn too_large(align: u64) -> AlignFromBytesError {
const fn too_large(align: u64) -> AlignFromBytesError {
AlignFromBytesError::TooLarge(align)
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr/Cargo.toml
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
# tidy-alphabetical-start
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
Expand Down
19 changes: 13 additions & 6 deletions compiler/rustc_attr/src/builtin.rs
@@ -1,5 +1,6 @@
//! Parsing and validation of builtin attributes

use rustc_abi::Align;
use rustc_ast::{self as ast, attr};
use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NodeId};
use rustc_ast_pretty::pprust;
Expand Down Expand Up @@ -919,10 +920,10 @@ pub enum ReprAttr {
ReprInt(IntType),
ReprRust,
ReprC,
ReprPacked(u32),
ReprPacked(Align),
ReprSimd,
ReprTransparent,
ReprAlign(u32),
ReprAlign(Align),
}

#[derive(Eq, PartialEq, Debug, Copy, Clone)]
Expand Down Expand Up @@ -968,7 +969,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
let hint = match item.name_or_empty() {
sym::Rust => Some(ReprRust),
sym::C => Some(ReprC),
sym::packed => Some(ReprPacked(1)),
sym::packed => Some(ReprPacked(Align::ONE)),
sym::simd => Some(ReprSimd),
sym::transparent => Some(ReprTransparent),
sym::align => {
Expand Down Expand Up @@ -1209,11 +1210,17 @@ fn allow_unstable<'a>(
})
}

pub fn parse_alignment(node: &ast::LitKind) -> Result<u32, &'static str> {
pub fn parse_alignment(node: &ast::LitKind) -> Result<Align, &'static str> {
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
// `Align::from_bytes` accepts 0 as an input, check is_power_of_two() first
if literal.get().is_power_of_two() {
// rustc_middle::ty::layout::Align restricts align to <= 2^29
if *literal <= 1 << 29 { Ok(literal.get() as u32) } else { Err("larger than 2^29") }
// Only possible error is larger than 2^29
literal
.get()
.try_into()
.ok()
.and_then(|v| Align::from_bytes(v).ok())
.ok_or("larger than 2^29")
} else {
Err("not a power of two")
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/attributes.rs
Expand Up @@ -417,7 +417,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));
}
if let Some(align) = codegen_fn_attrs.alignment {
llvm::set_alignment(llfn, align as usize);
llvm::set_alignment(llfn, align);
}
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
Expand Up @@ -17,14 +17,15 @@ use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::Coverage;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::Instance;
use rustc_target::abi::Align;

use std::cell::RefCell;

pub(crate) mod ffi;
pub(crate) mod map_data;
pub mod mapgen;

const VAR_ALIGN_BYTES: usize = 8;
const VAR_ALIGN_BYTES: Align = Align::EIGHT;

/// A context object for maintaining all state needed by the coverageinfo module.
pub struct CrateCoverageContext<'ll, 'tcx> {
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_codegen_llvm/src/llvm/mod.rs
Expand Up @@ -11,6 +11,7 @@ pub use self::RealPredicate::*;
use libc::c_uint;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_llvm::RustString;
use rustc_target::abi::Align;
use std::cell::RefCell;
use std::ffi::{CStr, CString};
use std::str::FromStr;
Expand Down Expand Up @@ -229,9 +230,9 @@ pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
}
}

pub fn set_alignment(llglobal: &Value, bytes: usize) {
pub fn set_alignment(llglobal: &Value, align: Align) {
unsafe {
ffi::LLVMSetAlignment(llglobal, bytes as c_uint);
ffi::LLVMSetAlignment(llglobal, align.bytes() as c_uint);
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Expand Up @@ -964,7 +964,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
for r in attr::parse_repr_attr(tcx.sess, attr) {
if let attr::ReprPacked(pack) = r
&& let Some(repr_pack) = repr.pack
&& pack as u64 != repr_pack.bytes()
&& pack != repr_pack
{
struct_span_code_err!(
tcx.dcx(),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -1,6 +1,7 @@
use crate::mir::mono::Linkage;
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_span::symbol::Symbol;
use rustc_target::abi::Align;
use rustc_target::spec::SanitizerSet;

#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
Expand Down Expand Up @@ -42,7 +43,7 @@ pub struct CodegenFnAttrs {
pub instruction_set: Option<InstructionSetAttr>,
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
/// aligned to.
pub alignment: Option<u32>,
pub alignment: Option<Align>,
}

#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Expand Up @@ -1523,7 +1523,6 @@ impl<'tcx> TyCtxt<'tcx> {
attr::ReprRust => ReprFlags::empty(),
attr::ReprC => ReprFlags::IS_C,
attr::ReprPacked(pack) => {
let pack = Align::from_bytes(pack as u64).unwrap();
min_pack = Some(if let Some(min_pack) = min_pack {
min_pack.min(pack)
} else {
Expand Down Expand Up @@ -1555,7 +1554,7 @@ impl<'tcx> TyCtxt<'tcx> {
ReprFlags::empty()
}
attr::ReprAlign(align) => {
max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
max_align = max_align.max(Some(align));
ReprFlags::empty()
}
});
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/repr/repr-align.rs
Expand Up @@ -15,6 +15,10 @@ struct S2(i32);
#[repr(align(536870912))] // ok: this is the largest accepted alignment
struct S3(i32);

#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
//~| ERROR: invalid `repr(align)` attribute: not a power of two
struct S4(i32);

#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
//~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
enum E0 { A, B }
Expand All @@ -30,4 +34,8 @@ enum E2 { A, B }
#[repr(align(536870912))] // ok: this is the largest accepted alignment
enum E3 { A, B }

#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
//~| ERROR: invalid `repr(align)` attribute: not a power of two
enum E4 { A, B }

fn main() {}
42 changes: 35 additions & 7 deletions tests/ui/repr/repr-align.stderr
Expand Up @@ -16,24 +16,36 @@ error[E0589]: invalid `repr(align)` attribute: larger than 2^29
LL | #[repr(align(4294967296))]
| ^^^^^^^^^^

error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:18:14
|
LL | #[repr(align(0))]
| ^

error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
--> $DIR/repr-align.rs:22:14
|
LL | #[repr(align(16.0))]
| ^^^^

error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:22:14
--> $DIR/repr-align.rs:26:14
|
LL | #[repr(align(15))]
| ^^

error[E0589]: invalid `repr(align)` attribute: larger than 2^29
--> $DIR/repr-align.rs:26:14
--> $DIR/repr-align.rs:30:14
|
LL | #[repr(align(4294967296))]
| ^^^^^^^^^^

error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:37:14
|
LL | #[repr(align(0))]
| ^

error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
--> $DIR/repr-align.rs:3:14
|
Expand All @@ -58,30 +70,46 @@ LL | #[repr(align(4294967296))]
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:18:14
|
LL | #[repr(align(0))]
| ^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
--> $DIR/repr-align.rs:22:14
|
LL | #[repr(align(16.0))]
| ^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:22:14
--> $DIR/repr-align.rs:26:14
|
LL | #[repr(align(15))]
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0589]: invalid `repr(align)` attribute: larger than 2^29
--> $DIR/repr-align.rs:26:14
--> $DIR/repr-align.rs:30:14
|
LL | #[repr(align(4294967296))]
| ^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 12 previous errors
error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:37:14
|
LL | #[repr(align(0))]
| ^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 16 previous errors

For more information about this error, try `rustc --explain E0589`.

0 comments on commit dc18eb5

Please sign in to comment.