Skip to content

Commit 9aad2d5

Browse files
nagisaest31
authored andcommitted
Add a way to retrieve constant value in 128 bits
Fixes rebase fallout, makes code correct in presence of 128-bit constants. This commit includes manual merge conflict resolution changes from a rebase by @est31.
1 parent 508fef5 commit 9aad2d5

File tree

10 files changed

+101
-70
lines changed

10 files changed

+101
-70
lines changed

src/librustc_const_math/int.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ mod ubounds {
5858
bounds!{u128: 0,
5959
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
6060
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX
61-
isize IMIN IMAX usize UMIN UMAX
61+
// do not add constants for isize/usize, because these are guaranteed to be wrong for
62+
// arbitrary host/target combinations
6263
}
6364
}
6465

@@ -78,11 +79,42 @@ mod ibounds {
7879
bounds!{i128,
7980
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
8081
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX
81-
isize IMIN IMAX usize UMIN UMAX
82+
// do not add constants for isize/usize, because these are guaranteed to be wrong for
83+
// arbitrary host/target combinations
8284
}
8385
}
8486

8587
impl ConstInt {
88+
/// Creates a new unsigned ConstInt with matching type while also checking that overflow does
89+
/// not happen.
90+
pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> {
91+
match ty {
92+
UintTy::U8 if val <= ubounds::U8MAX => Some(U8(val as u8)),
93+
UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)),
94+
UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)),
95+
UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)),
96+
UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
97+
.map(Usize),
98+
UintTy::U128 => Some(U128(val)),
99+
_ => None
100+
}
101+
}
102+
103+
/// Creates a new unsigned ConstInt with matching type while also checking that overflow does
104+
/// not happen.
105+
pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option<ConstInt> {
106+
match ty {
107+
IntTy::I8 if val <= ibounds::I8MAX => Some(I8(val as i8)),
108+
IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)),
109+
IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)),
110+
IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)),
111+
IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
112+
.map(Isize),
113+
IntTy::I128 => Some(I128(val)),
114+
_ => None
115+
}
116+
}
117+
86118
/// If either value is `Infer` or `InferSigned`, try to turn the value into the type of
87119
/// the other value. If both values have no type, don't do anything
88120
pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> {

src/librustc_llvm/ffi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ extern "C" {
582582
pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
583583
pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
584584
pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
585+
pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
586+
high: *mut u64, low: *mut u64) -> bool;
585587

586588

587589
// Operations on composite constants

src/librustc_trans/common.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,20 +592,34 @@ fn is_const_integral(v: ValueRef) -> bool {
592592
}
593593
}
594594

595-
pub fn const_to_opt_int(v: ValueRef) -> Option<i64> {
595+
596+
#[cfg(stage0)]
597+
pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option<u128> {
596598
unsafe {
597599
if is_const_integral(v) {
598-
Some(llvm::LLVMConstIntGetSExtValue(v))
600+
if !sign_ext {
601+
Some(llvm::LLVMConstIntGetZExtValue(v))
602+
} else {
603+
Some(llvm::LLVMConstIntGetSExtValue(v) as u64)
604+
}
599605
} else {
600606
None
601607
}
602608
}
603609
}
604610

605-
pub fn const_to_opt_uint(v: ValueRef) -> Option<u64> {
611+
#[cfg(not(stage0))]
612+
pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option<u128> {
606613
unsafe {
607614
if is_const_integral(v) {
608-
Some(llvm::LLVMConstIntGetZExtValue(v))
615+
let (mut lo, mut hi) = (0u64, 0u64);
616+
let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
617+
&mut hi as *mut u64, &mut lo as *mut u64);
618+
if success {
619+
Some(((hi as u128) << 64) | (lo as u128))
620+
} else {
621+
None
622+
}
609623
} else {
610624
None
611625
}

src/librustc_trans/consts.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use monomorphize::{Instance};
2424
use type_::Type;
2525
use type_of;
2626
use rustc::ty;
27-
use rustc_i128::{i128, u128};
2827

2928
use rustc::hir;
3029

src/librustc_trans/glue.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,12 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
346346

347347
// Choose max of two known alignments (combined value must
348348
// be aligned according to more restrictive of the two).
349-
let align = match (const_to_opt_uint(sized_align), const_to_opt_uint(unsized_align)) {
349+
let align = match (const_to_opt_u128(sized_align, false),
350+
const_to_opt_u128(unsized_align, false)) {
350351
(Some(sized_align), Some(unsized_align)) => {
351352
// If both alignments are constant, (the sized_align should always be), then
352353
// pick the correct alignment statically.
353-
C_uint(ccx, std::cmp::max(sized_align, unsized_align))
354+
C_uint(ccx, std::cmp::max(sized_align, unsized_align) as u64)
354355
}
355356
_ => bcx.select(bcx.icmp(llvm::IntUGT, sized_align, unsized_align),
356357
sized_align,

src/librustc_trans/intrinsic.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ use syntax::symbol::Symbol;
3232
use rustc::session::Session;
3333
use syntax_pos::Span;
3434

35+
use rustc_i128::u128;
36+
3537
use std::cmp::Ordering;
3638
use std::iter;
3739

@@ -1019,15 +1021,15 @@ fn generic_simd_intrinsic<'a, 'tcx>(
10191021
in_elem, in_ty,
10201022
ret_ty, ret_ty.simd_type(tcx));
10211023

1022-
let total_len = in_len as u64 * 2;
1024+
let total_len = in_len as u128 * 2;
10231025

10241026
let vector = llargs[2];
10251027

10261028
let indices: Option<Vec<_>> = (0..n)
10271029
.map(|i| {
10281030
let arg_idx = i;
10291031
let val = const_get_elt(vector, &[i as libc::c_uint]);
1030-
match const_to_opt_uint(val) {
1032+
match const_to_opt_u128(val, true) {
10311033
None => {
10321034
emit_error!("shuffle index #{} is not a constant", arg_idx);
10331035
None

src/librustc_trans/mir/block.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
269269

270270
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
271271
let cond = self.trans_operand(&bcx, cond).immediate();
272-
let mut const_cond = common::const_to_opt_uint(cond).map(|c| c == 1);
272+
let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
273273

274274
// This case can currently arise only from functions marked
275275
// with #[rustc_inherit_overflow_checks] and inlined from
@@ -322,14 +322,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
322322
let len = self.trans_operand(&mut bcx, len).immediate();
323323
let index = self.trans_operand(&mut bcx, index).immediate();
324324

325-
let const_err = common::const_to_opt_uint(len).and_then(|len| {
326-
common::const_to_opt_uint(index).map(|index| {
327-
ErrKind::IndexOutOfBounds {
328-
len: len,
329-
index: index
330-
}
331-
})
332-
});
325+
let const_err = common::const_to_opt_u128(len, false)
326+
.and_then(|len| common::const_to_opt_u128(index, false)
327+
.map(|index| ErrKind::IndexOutOfBounds {
328+
len: len as u64,
329+
index: index as u64
330+
}));
333331

334332
let file_line = C_struct(bcx.ccx, &[filename, line], false);
335333
let align = llalign_of_min(bcx.ccx, common::val_ty(file_line));

src/librustc_trans/mir/constant.rs

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc::middle::const_val::ConstVal;
1313
use rustc_const_eval::{ErrKind, ConstEvalErr, report_const_eval_err};
1414
use rustc_const_math::ConstInt::*;
1515
use rustc_const_math::ConstFloat::*;
16-
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstMathErr};
16+
use rustc_const_math::{ConstInt, ConstMathErr};
1717
use rustc::hir::def_id::DefId;
1818
use rustc::infer::TransNormalize;
1919
use rustc::mir;
@@ -27,23 +27,23 @@ use callee::Callee;
2727
use common::{self, BlockAndBuilder, CrateContext, const_get_elt, val_ty};
2828
use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral, C_big_integral};
2929
use common::{C_null, C_struct, C_str_slice, C_undef, C_uint};
30-
use common::{const_to_opt_int, const_to_opt_uint};
30+
use common::{const_to_opt_u128};
3131
use consts;
3232
use monomorphize::{self, Instance};
3333
use type_of;
3434
use type_::Type;
3535
use value::Value;
3636

37-
use syntax::ast;
3837
use syntax_pos::Span;
39-
use rustc_i128::u128;
4038

4139
use std::fmt;
4240
use std::ptr;
4341

4442
use super::operand::{OperandRef, OperandValue};
4543
use super::MirContext;
4644

45+
use rustc_i128::{u128, i128};
46+
4747
/// A sized constant rvalue.
4848
/// The LLVM type might not be the same for a single Rust type,
4949
/// e.g. each enum variant would have its own LLVM struct type.
@@ -431,15 +431,15 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
431431
mir::ProjectionElem::Index(ref index) => {
432432
let llindex = self.const_operand(index, span)?.llval;
433433

434-
let iv = if let Some(iv) = common::const_to_opt_uint(llindex) {
434+
let iv = if let Some(iv) = common::const_to_opt_u128(llindex, false) {
435435
iv
436436
} else {
437437
span_bug!(span, "index is not an integer-constant expression")
438438
};
439439

440440
// Produce an undef instead of a LLVM assertion on OOB.
441441
let len = common::const_to_uint(tr_base.len(self.ccx));
442-
let llelem = if iv < len {
442+
let llelem = if iv < len as u128 {
443443
const_get_elt(base.llval, &[iv as u32])
444444
} else {
445445
C_undef(type_of::type_of(self.ccx, projected_ty))
@@ -797,49 +797,14 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
797797

798798
fn to_const_int(value: ValueRef, t: Ty, tcx: TyCtxt) -> Option<ConstInt> {
799799
match t.sty {
800-
ty::TyInt(int_type) => const_to_opt_int(value).and_then(|input| match int_type {
801-
ast::IntTy::I8 => {
802-
assert_eq!(input as i8 as i64, input);
803-
Some(ConstInt::I8(input as i8))
804-
},
805-
ast::IntTy::I16 => {
806-
assert_eq!(input as i16 as i64, input);
807-
Some(ConstInt::I16(input as i16))
808-
},
809-
ast::IntTy::I32 => {
810-
assert_eq!(input as i32 as i64, input);
811-
Some(ConstInt::I32(input as i32))
812-
},
813-
ast::IntTy::I64 => {
814-
Some(ConstInt::I64(input))
815-
},
816-
ast::IntTy::Is => {
817-
ConstIsize::new(input, tcx.sess.target.int_type)
818-
.ok().map(ConstInt::Isize)
819-
},
820-
}),
821-
ty::TyUint(uint_type) => const_to_opt_uint(value).and_then(|input| match uint_type {
822-
ast::UintTy::U8 => {
823-
assert_eq!(input as u8 as u64, input);
824-
Some(ConstInt::U8(input as u8))
825-
},
826-
ast::UintTy::U16 => {
827-
assert_eq!(input as u16 as u64, input);
828-
Some(ConstInt::U16(input as u16))
829-
},
830-
ast::UintTy::U32 => {
831-
assert_eq!(input as u32 as u64, input);
832-
Some(ConstInt::U32(input as u32))
833-
},
834-
ast::UintTy::U64 => {
835-
Some(ConstInt::U64(input))
836-
},
837-
ast::UintTy::Us => {
838-
ConstUsize::new(input, tcx.sess.target.uint_type)
839-
.ok().map(ConstInt::Usize)
840-
},
841-
}),
842-
_ => None,
800+
ty::TyInt(int_type) => const_to_opt_u128(value, true)
801+
.and_then(|input| ConstInt::new_signed(input as i128, int_type,
802+
tcx.sess.target.int_type)),
803+
ty::TyUint(uint_type) => const_to_opt_u128(value, false)
804+
.and_then(|input| ConstInt::new_unsigned(input, uint_type,
805+
tcx.sess.target.uint_type)),
806+
_ => None
807+
843808
}
844809
}
845810

src/librustdoc/clean/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,7 @@ impl From<ast::IntTy> for PrimitiveType {
16531653
ast::IntTy::I16 => PrimitiveType::I16,
16541654
ast::IntTy::I32 => PrimitiveType::I32,
16551655
ast::IntTy::I64 => PrimitiveType::I64,
1656+
ast::IntTy::I128 => PrimitiveType::I128,
16561657
}
16571658
}
16581659
}
@@ -1665,6 +1666,7 @@ impl From<ast::UintTy> for PrimitiveType {
16651666
ast::UintTy::U16 => PrimitiveType::U16,
16661667
ast::UintTy::U32 => PrimitiveType::U32,
16671668
ast::UintTy::U64 => PrimitiveType::U64,
1669+
ast::UintTy::U128 => PrimitiveType::U128,
16681670
}
16691671
}
16701672
}
@@ -2489,7 +2491,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
24892491
fn build_deref_target_impls(cx: &DocContext,
24902492
items: &[Item],
24912493
ret: &mut Vec<Item>) {
2492-
use PrimitiveType::*;
2494+
use self::PrimitiveType::*;
24932495
let tcx = cx.tcx;
24942496

24952497
for item in items {

src/rustllvm/RustWrapper.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,22 @@ extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
14561456

14571457
extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) {
14581458
LLVMSetLinkage(V, from_rust(RustLinkage));
1459+
1460+
// Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1461+
// the common sizes (1, 8, 16, 32, 64, 128 bits)
1462+
extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1463+
{
1464+
auto C = unwrap<llvm::ConstantInt>(CV);
1465+
if (C->getBitWidth() > 128) { return false; }
1466+
APInt AP;
1467+
if (sext) {
1468+
AP = C->getValue().sextOrSelf(128);
1469+
} else {
1470+
AP = C->getValue().zextOrSelf(128);
1471+
}
1472+
*low = AP.getLoBits(64).getZExtValue();
1473+
*high = AP.getHiBits(64).getZExtValue();
1474+
return true;
14591475
}
14601476

14611477
extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {

0 commit comments

Comments
 (0)