Use the Align
type when parsing alignment attributes
This commit is contained in:
parent
2f090c30dd
commit
6e5f1dacf3
12 changed files with 74 additions and 26 deletions
|
@ -3560,6 +3560,7 @@ dependencies = [
|
||||||
name = "rustc_attr"
|
name = "rustc_attr"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"rustc_abi",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_ast_pretty",
|
"rustc_ast_pretty",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
|
|
|
@ -698,6 +698,7 @@ impl fmt::Display for AlignFromBytesError {
|
||||||
|
|
||||||
impl Align {
|
impl Align {
|
||||||
pub const ONE: Align = Align { pow2: 0 };
|
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.
|
// LLVM has a maximal supported alignment of 2^29, we inherit that.
|
||||||
pub const MAX: Align = Align { pow2: 29 };
|
pub const MAX: Align = Align { pow2: 29 };
|
||||||
|
|
||||||
|
@ -707,19 +708,19 @@ impl Align {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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.
|
// Treat an alignment of 0 bytes like 1-byte alignment.
|
||||||
if align == 0 {
|
if align == 0 {
|
||||||
return Ok(Align::ONE);
|
return Ok(Align::ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
fn not_power_of_2(align: u64) -> AlignFromBytesError {
|
const fn not_power_of_2(align: u64) -> AlignFromBytesError {
|
||||||
AlignFromBytesError::NotPowerOfTwo(align)
|
AlignFromBytesError::NotPowerOfTwo(align)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
fn too_large(align: u64) -> AlignFromBytesError {
|
const fn too_large(align: u64) -> AlignFromBytesError {
|
||||||
AlignFromBytesError::TooLarge(align)
|
AlignFromBytesError::TooLarge(align)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
|
rustc_abi = { path = "../rustc_abi" }
|
||||||
rustc_ast = { path = "../rustc_ast" }
|
rustc_ast = { path = "../rustc_ast" }
|
||||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Parsing and validation of builtin attributes
|
//! Parsing and validation of builtin attributes
|
||||||
|
|
||||||
|
use rustc_abi::Align;
|
||||||
use rustc_ast::{self as ast, attr};
|
use rustc_ast::{self as ast, attr};
|
||||||
use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NodeId};
|
use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NodeId};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
|
@ -919,10 +920,10 @@ pub enum ReprAttr {
|
||||||
ReprInt(IntType),
|
ReprInt(IntType),
|
||||||
ReprRust,
|
ReprRust,
|
||||||
ReprC,
|
ReprC,
|
||||||
ReprPacked(u32),
|
ReprPacked(Align),
|
||||||
ReprSimd,
|
ReprSimd,
|
||||||
ReprTransparent,
|
ReprTransparent,
|
||||||
ReprAlign(u32),
|
ReprAlign(Align),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||||
|
@ -968,7 +969,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
||||||
let hint = match item.name_or_empty() {
|
let hint = match item.name_or_empty() {
|
||||||
sym::Rust => Some(ReprRust),
|
sym::Rust => Some(ReprRust),
|
||||||
sym::C => Some(ReprC),
|
sym::C => Some(ReprC),
|
||||||
sym::packed => Some(ReprPacked(1)),
|
sym::packed => Some(ReprPacked(Align::ONE)),
|
||||||
sym::simd => Some(ReprSimd),
|
sym::simd => Some(ReprSimd),
|
||||||
sym::transparent => Some(ReprTransparent),
|
sym::transparent => Some(ReprTransparent),
|
||||||
sym::align => {
|
sym::align => {
|
||||||
|
@ -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 {
|
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() {
|
if literal.get().is_power_of_two() {
|
||||||
// rustc_middle::ty::layout::Align restricts align to <= 2^29
|
// Only possible error is larger than 2^29
|
||||||
if *literal <= 1 << 29 { Ok(literal.get() as u32) } else { Err("larger than 2^29") }
|
literal
|
||||||
|
.get()
|
||||||
|
.try_into()
|
||||||
|
.ok()
|
||||||
|
.and_then(|v| Align::from_bytes(v).ok())
|
||||||
|
.ok_or("larger than 2^29")
|
||||||
} else {
|
} else {
|
||||||
Err("not a power of two")
|
Err("not a power of two")
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,7 +417,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
||||||
to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));
|
to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));
|
||||||
}
|
}
|
||||||
if let Some(align) = codegen_fn_attrs.alignment {
|
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));
|
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use rustc_middle::mir::coverage::CoverageKind;
|
||||||
use rustc_middle::mir::Coverage;
|
use rustc_middle::mir::Coverage;
|
||||||
use rustc_middle::ty::layout::HasTyCtxt;
|
use rustc_middle::ty::layout::HasTyCtxt;
|
||||||
use rustc_middle::ty::Instance;
|
use rustc_middle::ty::Instance;
|
||||||
|
use rustc_target::abi::Align;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ pub(crate) mod ffi;
|
||||||
pub(crate) mod map_data;
|
pub(crate) mod map_data;
|
||||||
pub mod mapgen;
|
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.
|
/// A context object for maintaining all state needed by the coverageinfo module.
|
||||||
pub struct CrateCoverageContext<'ll, 'tcx> {
|
pub struct CrateCoverageContext<'ll, 'tcx> {
|
||||||
|
@ -227,7 +228,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
|
||||||
llvm::set_global_constant(llglobal, true);
|
llvm::set_global_constant(llglobal, true);
|
||||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||||
llvm::set_section(llglobal, &covmap_section_name);
|
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);
|
cx.add_used_global(llglobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +258,7 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
|
||||||
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
|
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
|
||||||
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
|
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
|
||||||
llvm::set_section(llglobal, covfun_section_name);
|
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);
|
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
|
||||||
cx.add_used_global(llglobal);
|
cx.add_used_global(llglobal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub use self::RealPredicate::*;
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_llvm::RustString;
|
use rustc_llvm::RustString;
|
||||||
|
use rustc_target::abi::Align;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -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 {
|
unsafe {
|
||||||
ffi::LLVMSetAlignment(llglobal, bytes as c_uint);
|
ffi::LLVMSetAlignment(llglobal, align.bytes() as c_uint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
for r in attr::parse_repr_attr(tcx.sess, attr) {
|
||||||
if let attr::ReprPacked(pack) = r
|
if let attr::ReprPacked(pack) = r
|
||||||
&& let Some(repr_pack) = repr.pack
|
&& let Some(repr_pack) = repr.pack
|
||||||
&& pack as u64 != repr_pack.bytes()
|
&& pack != repr_pack
|
||||||
{
|
{
|
||||||
struct_span_code_err!(
|
struct_span_code_err!(
|
||||||
tcx.dcx(),
|
tcx.dcx(),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::mir::mono::Linkage;
|
use crate::mir::mono::Linkage;
|
||||||
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
|
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
use rustc_target::abi::Align;
|
||||||
use rustc_target::spec::SanitizerSet;
|
use rustc_target::spec::SanitizerSet;
|
||||||
|
|
||||||
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
|
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||||
|
@ -42,7 +43,7 @@ pub struct CodegenFnAttrs {
|
||||||
pub instruction_set: Option<InstructionSetAttr>,
|
pub instruction_set: Option<InstructionSetAttr>,
|
||||||
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
|
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
|
||||||
/// aligned to.
|
/// aligned to.
|
||||||
pub alignment: Option<u32>,
|
pub alignment: Option<Align>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
|
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
|
||||||
|
|
|
@ -1523,7 +1523,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
attr::ReprRust => ReprFlags::empty(),
|
attr::ReprRust => ReprFlags::empty(),
|
||||||
attr::ReprC => ReprFlags::IS_C,
|
attr::ReprC => ReprFlags::IS_C,
|
||||||
attr::ReprPacked(pack) => {
|
attr::ReprPacked(pack) => {
|
||||||
let pack = Align::from_bytes(pack as u64).unwrap();
|
|
||||||
min_pack = Some(if let Some(min_pack) = min_pack {
|
min_pack = Some(if let Some(min_pack) = min_pack {
|
||||||
min_pack.min(pack)
|
min_pack.min(pack)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1555,7 +1554,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
ReprFlags::empty()
|
ReprFlags::empty()
|
||||||
}
|
}
|
||||||
attr::ReprAlign(align) => {
|
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()
|
ReprFlags::empty()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,6 +15,10 @@ struct S2(i32);
|
||||||
#[repr(align(536870912))] // ok: this is the largest accepted alignment
|
#[repr(align(536870912))] // ok: this is the largest accepted alignment
|
||||||
struct S3(i32);
|
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
|
#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
|
||||||
//~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
|
//~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
|
||||||
enum E0 { A, B }
|
enum E0 { A, B }
|
||||||
|
@ -30,4 +34,8 @@ enum E2 { A, B }
|
||||||
#[repr(align(536870912))] // ok: this is the largest accepted alignment
|
#[repr(align(536870912))] // ok: this is the largest accepted alignment
|
||||||
enum E3 { A, B }
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -16,24 +16,36 @@ error[E0589]: invalid `repr(align)` attribute: larger than 2^29
|
||||||
LL | #[repr(align(4294967296))]
|
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
|
--> $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))]
|
LL | #[repr(align(16.0))]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error[E0589]: invalid `repr(align)` attribute: not a power of two
|
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))]
|
LL | #[repr(align(15))]
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error[E0589]: invalid `repr(align)` attribute: larger than 2^29
|
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))]
|
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
|
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
|
||||||
--> $DIR/repr-align.rs:3:14
|
--> $DIR/repr-align.rs:3:14
|
||||||
|
|
|
|
||||||
|
@ -58,16 +70,24 @@ LL | #[repr(align(4294967296))]
|
||||||
|
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
= 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
|
--> $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))]
|
LL | #[repr(align(16.0))]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
error[E0589]: invalid `repr(align)` attribute: not a power of two
|
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))]
|
LL | #[repr(align(15))]
|
||||||
| ^^
|
| ^^
|
||||||
|
@ -75,13 +95,21 @@ LL | #[repr(align(15))]
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
error[E0589]: invalid `repr(align)` attribute: larger than 2^29
|
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))]
|
LL | #[repr(align(4294967296))]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
= 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`.
|
For more information about this error, try `rustc --explain E0589`.
|
||||||
|
|
Loading…
Add table
Reference in a new issue