Skip to content

Commit

Permalink
Auto merge of #120080 - cuviper:128-align-packed, r=<try>
Browse files Browse the repository at this point in the history
[WIP] pack u128 in the compiler to mitigate new alignment

This is based on #116672, adding a new `#[repr(packed(8))]` wrapper on `u128` to avoid changing any of the compiler's size assertions. This is needed in two places:

* `SwitchTargets`, otherwise its `SmallVec<[u128; 1]>` gets padded up to 32 bytes.
* `LitKind::Int`, so that entire `enum` can stay 24 bytes.
  * This change definitely has far-reaching effects though, since it's public.

r? ghost
  • Loading branch information
bors committed Jan 18, 2024
2 parents 6ae4cfb + 6718116 commit 966f88e
Show file tree
Hide file tree
Showing 91 changed files with 256 additions and 151 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub use UnsafeSource::*;
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter};
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
use rustc_data_structures::packed::Pu128;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
Expand Down Expand Up @@ -1829,7 +1830,7 @@ pub enum LitKind {
/// A character literal (`'a'`).
Char(char),
/// An integer literal (`1`).
Int(u128, LitIntType),
Int(Pu128, LitIntType),
/// A float literal (`1.0`, `1f64` or `1E10f64`). The pre-suffix part is
/// stored as a symbol rather than `f64` so that `LitKind` can impl `Eq`
/// and `Hash`.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/util/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
};

let s = &s[if base != 10 { 2 } else { 0 }..];
u128::from_str_radix(s, base).map(|i| LitKind::Int(i, ty)).map_err(|_| {
u128::from_str_radix(s, base).map(|i| LitKind::Int(i.into(), ty)).map_err(|_| {
// Small bases are lexed as if they were base 10, e.g, the string
// might be `0b10201`. This will cause the conversion above to fail,
// but these kinds of errors are already reported by the lexer.
Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1908,15 +1908,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
let lit = self.arena.alloc(hir::Lit {
span: sp,
node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
node: ast::LitKind::Int(
(value as u128).into(),
ast::LitIntType::Unsigned(ast::UintTy::Usize),
),
});
self.expr(sp, hir::ExprKind::Lit(lit))
}

pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
let lit = self.arena.alloc(hir::Lit {
span: sp,
node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)),
node: ast::LitKind::Int(
u128::from(value).into(),
ast::LitIntType::Unsigned(ast::UintTy::U32),
),
});
self.expr(sp, hir::ExprKind::Lit(lit))
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1185,9 +1185,9 @@ fn allow_unstable<'a>(

pub fn parse_alignment(node: &ast::LitKind) -> Result<u32, &'static str> {
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
if literal.is_power_of_two() {
if literal.get().is_power_of_two() {
// rustc_middle::ty::layout::Align restricts align to <= 2^29
if *literal <= 1 << 29 { Ok(*literal as u32) } else { Err("larger than 2^29") }
if *literal <= 1 << 29 { Ok(literal.get() as u32) } else { Err("larger than 2^29") }
} else {
Err("not a power of two")
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
match kind {
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
Some(Self::Int { span, name, int: *int })
Some(Self::Int { span, name, int: int.get() })
}
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
_ => None,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_builtin_macros/src/concat_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn invalid_type_err(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
)) => {
assert!(val > u8::MAX.into()); // must be an error
assert!(val.get() > u8::MAX.into()); // must be an error
dcx.emit_err(ConcatBytesOob { span });
}
Ok(ast::LitKind::Int(_, _)) => {
Expand Down Expand Up @@ -86,7 +86,7 @@ fn handle_array_element(
Ok(ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
)) if val <= u8::MAX.into() => Some(val as u8),
)) if val.get() <= u8::MAX.into() => Some(val.get() as u8),

Ok(ast::LitKind::Byte(val)) => Some(val),
Ok(ast::LitKind::ByteStr(..)) => {
Expand Down Expand Up @@ -148,7 +148,7 @@ pub fn expand_concat_bytes(
if let Some(elem) =
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
{
for _ in 0..count_val {
for _ in 0..count_val.get() {
accumulator.push(elem);
}
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ pub unsafe fn create_module<'ll>(
.replace("-Fi64", "");
}
}
if llvm_version < (18, 0, 0) {
if sess.target.arch == "x86" || sess.target.arch == "x86_64" {
// LLVM 18 adjusts i128 to be 128-bit aligned on x86 variants.
// Earlier LLVMs leave this as default alignment, so remove it.
// See https://reviews.llvm.org/D86310
target_data_layout = target_data_layout.replace("-i128:128", "");
}
}

// Ensure the data-layout values hardcoded remain the defaults.
if sess.target.is_builtin {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
// if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
// about LINK.EXE failing.)
if *ordinal <= u16::MAX as u128 {
Some(*ordinal as u16)
Some(ordinal.get() as u16)
} else {
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
tcx.dcx()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub mod aligned;
pub mod frozen;
mod hashes;
pub mod owned_slice;
pub mod packed;
pub mod sso;
pub mod steal;
pub mod tagged_ptr;
Expand Down
71 changes: 71 additions & 0 deletions compiler/rustc_data_structures/src/packed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::stable_hasher::{HashStable, StableHasher};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cmp::Ordering;
use std::fmt;

#[repr(packed(8))]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Pu128(pub u128);

impl Pu128 {
#[inline]
pub fn get(self) -> u128 {
self.0
}
}

impl From<u128> for Pu128 {
#[inline]
fn from(value: u128) -> Self {
Self(value)
}
}

impl PartialEq<u128> for Pu128 {
#[inline]
fn eq(&self, other: &u128) -> bool {
({ self.0 }) == *other
}
}

impl PartialOrd<u128> for Pu128 {
#[inline]
fn partial_cmp(&self, other: &u128) -> Option<Ordering> {
{ self.0 }.partial_cmp(other)
}
}

impl fmt::Display for Pu128 {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
{ self.0 }.fmt(f)
}
}

impl fmt::UpperHex for Pu128 {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
{ self.0 }.fmt(f)
}
}

impl<CTX> HashStable<CTX> for Pu128 {
#[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
{ self.0 }.hash_stable(ctx, hasher)
}
}

impl<S: Encoder> Encodable<S> for Pu128 {
#[inline]
fn encode(&self, s: &mut S) {
{ self.0 }.encode(s);
}
}

impl<D: Decoder> Decodable<D> for Pu128 {
#[inline]
fn decode(d: &mut D) -> Self {
Self(u128::decode(d))
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/mbe/metavar_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ fn parse_depth<'sess>(
};
if let Ok(lit_kind) = LitKind::from_token_lit(*lit)
&& let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind
&& let Ok(n_usize) = usize::try_from(n_u128)
&& let Ok(n_usize) = usize::try_from(n_u128.get())
{
Ok(n_usize)
} else {
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2982,10 +2982,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// fixed expression:
if let ExprKind::Lit(lit) = idx.kind
&& let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node
&& i < types
.len()
.try_into()
.expect("expected tuple index to be < usize length")
&& i.get()
< types
.len()
.try_into()
.expect("expected tuple index to be < usize length")
{
err.span_suggestion(
brackets_span,
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::ty::TypeAndMut;
use core::cmp::min;
use core::iter;
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_data_structures::packed::Pu128;
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::Res;
Expand Down Expand Up @@ -1409,8 +1410,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let (_, suffix) = snippet.split_at(snippet.len() - 3);
let value = match suffix {
"f32" => (lit - 0xf32) / (16 * 16 * 16),
"f64" => (lit - 0xf64) / (16 * 16 * 16),
"f32" => (lit.get() - 0xf32) / (16 * 16 * 16),
"f64" => (lit.get() - 0xf64) / (16 * 16 * 16),
_ => return false,
};
err.span_suggestions(
Expand Down Expand Up @@ -1440,7 +1441,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

// Provided expression needs to be a literal `0`.
let ExprKind::Lit(Spanned { node: rustc_ast::LitKind::Int(0, _), span }) = expr.kind else {
let ExprKind::Lit(Spanned { node: rustc_ast::LitKind::Int(Pu128(0), _), span }) = expr.kind
else {
return false;
};

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::method::MethodCallee;
use super::{has_expected_num_generic_args, FnCtxt};
use crate::Expectation;
use rustc_ast as ast;
use rustc_data_structures::packed::Pu128;
use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
Expand Down Expand Up @@ -834,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Expr {
kind:
hir::ExprKind::Lit(Spanned {
node: ast::LitKind::Int(1, _),
node: ast::LitKind::Int(Pu128(1), _),
..
}),
..
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/invalid_from_utf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
.map(|e| match &e.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
LitKind::Byte(b) => Some(*b),
LitKind::Int(b, _) => Some(*b as u8),
LitKind::Int(b, _) => Some(b.get() as u8),
_ => None,
},
_ => None,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ fn lint_uint_literal<'tcx>(
let lit_val: u128 = match lit.node {
// _v is u8, within range by definition
ast::LitKind::Byte(_v) => return,
ast::LitKind::Int(v, _) => v,
ast::LitKind::Int(v, _) => v.get(),
_ => bug!(),
};
if lit_val < min || lit_val > max {
Expand Down Expand Up @@ -555,7 +555,7 @@ fn lint_literal<'tcx>(
ty::Int(t) => {
match lit.node {
ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
lint_int_literal(cx, type_limits, e, lit, t, v)
lint_int_literal(cx, type_limits, e, lit, t, v.get())
}
_ => bug!(),
};
Expand Down Expand Up @@ -842,7 +842,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
ast::LitKind::Int(
v,
ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed,
) => v as i128,
) => v.get() as i128,
_ => return true,
},
_ => bug!(),
Expand All @@ -853,7 +853,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
let (min, max): (u128, u128) = uint_ty_range(uint_ty);
let lit_val: u128 = match lit.kind {
hir::ExprKind::Lit(li) => match li.node {
ast::LitKind::Int(v, _) => v,
ast::LitKind::Int(v, _) => v.get(),
_ => return true,
},
_ => bug!(),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::ty::{self, List, Ty};
use crate::ty::{Region, UserTypeAnnotationIndex};

use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_data_structures::packed::Pu128;
use rustc_hir::def_id::DefId;
use rustc_hir::{self, CoroutineKind};
use rustc_index::IndexVec;
Expand Down Expand Up @@ -829,7 +830,7 @@ impl TerminatorKind<'_> {
pub struct SwitchTargets {
/// Possible values. The locations to branch to in each case
/// are found in the corresponding indices from the `targets` vector.
pub(super) values: SmallVec<[u128; 1]>,
pub(super) values: SmallVec<[Pu128; 1]>,

/// Possible branch sites. The last element of this vector is used
/// for the otherwise branch, so targets.len() == values.len() + 1
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_middle/src/mir/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use rustc_hir::LangItem;
use smallvec::SmallVec;

use super::TerminatorKind;
use rustc_data_structures::packed::Pu128;
use rustc_macros::HashStable;
use std::slice;

Expand All @@ -14,15 +15,16 @@ impl SwitchTargets {
/// The iterator may be empty, in which case the `SwitchInt` instruction is equivalent to
/// `goto otherwise;`.
pub fn new(targets: impl Iterator<Item = (u128, BasicBlock)>, otherwise: BasicBlock) -> Self {
let (values, mut targets): (SmallVec<_>, SmallVec<_>) = targets.unzip();
let (values, mut targets): (SmallVec<_>, SmallVec<_>) =
targets.map(|(v, t)| (Pu128(v), t)).unzip();
targets.push(otherwise);
Self { values, targets }
}

/// Builds a switch targets definition that jumps to `then` if the tested value equals `value`,
/// and to `else_` if not.
pub fn static_if(value: u128, then: BasicBlock, else_: BasicBlock) -> Self {
Self { values: smallvec![value], targets: smallvec![then, else_] }
Self { values: smallvec![Pu128(value)], targets: smallvec![then, else_] }
}

/// Inverse of `SwitchTargets::static_if`.
Expand All @@ -31,7 +33,7 @@ impl SwitchTargets {
if let &[value] = &self.values[..]
&& let &[then, else_] = &self.targets[..]
{
Some((value, then, else_))
Some((value.get(), then, else_))
} else {
None
}
Expand Down Expand Up @@ -75,15 +77,15 @@ impl SwitchTargets {
}

pub struct SwitchTargetsIter<'a> {
inner: iter::Zip<slice::Iter<'a, u128>, slice::Iter<'a, BasicBlock>>,
inner: iter::Zip<slice::Iter<'a, Pu128>, slice::Iter<'a, BasicBlock>>,
}

impl<'a> Iterator for SwitchTargetsIter<'a> {
type Item = (u128, BasicBlock);

#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(val, bb)| (*val, *bb))
self.inner.next().map(|(val, bb)| (val.get(), *bb))
}

#[inline]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ impl<'tcx> TyCtxt<'tcx> {
],
) = attr.meta_item_list().as_deref()
{
Bound::Included(a)
Bound::Included(a.get())
} else {
self.dcx().span_delayed_bug(
attr.span,
Expand Down
Loading

0 comments on commit 966f88e

Please sign in to comment.