Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the Align type when parsing alignment attributes #122972

Merged
merged 1 commit into from Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
7 changes: 4 additions & 3 deletions 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: Align = Align::EIGHT;

/// A context object for maintaining all state needed by the coverageinfo module.
pub struct CrateCoverageContext<'ll, 'tcx> {
Expand Down Expand Up @@ -227,7 +228,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
llvm::set_global_constant(llglobal, true);
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::set_section(llglobal, &covmap_section_name);
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
llvm::set_alignment(llglobal, VAR_ALIGN);
cx.add_used_global(llglobal);
}

Expand Down Expand Up @@ -257,7 +258,7 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
llvm::set_section(llglobal, covfun_section_name);
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
llvm::set_alignment(llglobal, VAR_ALIGN);
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
cx.add_used_global(llglobal);
}
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`.