pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
// Compiles a comparison between two things.
-//
-// NB: This must produce an i1, not a Rust bool (i8).
fn compare_values<'a>(
cx: &'a Block<'a>,
lhs: ValueRef,
format!("comparison of `{}`",
cx.ty_to_str(rhs_t)).as_slice(),
StrEqFnLangItem);
- let result = callee::trans_lang_call(cx, did, [lhs, rhs], None);
- Result {
- bcx: result.bcx,
- val: bool_to_i1(result.bcx, result.val)
- }
+ callee::trans_lang_call(cx, did, [lhs, rhs], None)
}
let _icx = push_ctxt("compare_values");
format!("comparison of `{}`",
cx.ty_to_str(rhs_t)).as_slice(),
UniqStrEqFnLangItem);
- let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None);
- Result {
- bcx: result.bcx,
- val: bool_to_i1(result.bcx, result.val)
- }
+ callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None)
}
_ => cx.sess().bug("only strings supported in compare_values"),
},
// Used only for creating scalar comparison glue.
pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
-// NB: This produces an i1, not a Rust bool (i8).
pub fn compare_scalar_types<'a>(
cx: &'a Block<'a>,
lhs: ValueRef,
}
_ => {}
}
+
+ match ty::get(ret_ty).sty {
+ ty::ty_bool => {
+ attrs.push((lib::llvm::ReturnIndex as uint, lib::llvm::ZExtAttribute as u64));
+ }
+ _ => {}
+ }
}
for (idx, &t) in fn_sig.inputs.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
attrs.push((idx, lib::llvm::NoCaptureAttribute as u64));
attrs.push((idx, lib::llvm::NonNullAttribute as u64));
}
+ ty::ty_bool => {
+ attrs.push((idx, lib::llvm::ZExtAttribute as u64));
+ }
// `~` pointer parameters never alias because ownership is transferred
ty::ty_uniq(_) => {
attrs.push((idx, lib::llvm::NoAliasAttribute as u64));
#![allow(non_uppercase_pattern_statics)]
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
-use lib::llvm::StructRetAttribute;
+use lib::llvm::{StructRetAttribute, ZExtAttribute};
use middle::trans::cabi::{FnType, ArgType};
use middle::trans::context::CrateContext;
use middle::trans::type_::Type;
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
- return ArgType::direct(ty, None, None, None);
+ let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ return ArgType::direct(ty, None, None, attr);
}
let size = ty_size(ty);
if size <= 4 {
fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
- return ArgType::direct(ty, None, None, None);
+ let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ return ArgType::direct(ty, None, None, attr);
}
let align = ty_align(ty);
let size = ty_size(ty);
use libc::c_uint;
use std::cmp;
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
-use lib::llvm::StructRetAttribute;
+use lib::llvm::{StructRetAttribute, ZExtAttribute};
use middle::trans::context::CrateContext;
use middle::trans::cabi::*;
use middle::trans::type_::Type;
}
}
-fn classify_ret_ty(ty: Type) -> ArgType {
+fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
- ArgType::direct(ty, None, None, None)
+ let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ ArgType::direct(ty, None, None, attr)
} else {
ArgType::indirect(ty, Some(StructRetAttribute))
}
*offset += align_up_to(size, align * 8) / 8;
if is_reg_ty(ty) {
- ArgType::direct(ty, None, None, None)
+ let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ ArgType::direct(ty, None, None, attr)
} else {
ArgType::direct(
ty,
rty: Type,
ret_def: bool) -> FnType {
let ret_ty = if ret_def {
- classify_ret_ty(rty)
+ classify_ret_ty(ccx, rty)
} else {
ArgType::direct(Type::void(ccx), None, None, None)
};
}
}
} else {
- ret_ty = ArgType::direct(rty, None, None, None);
+ let attr = if rty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ ret_ty = ArgType::direct(rty, None, None, attr);
}
for &t in atys.iter() {
ArgType::indirect(t, Some(ByValAttribute))
}
}
- _ => ArgType::direct(t, None, None, None),
+ _ => {
+ let attr = if t == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ ArgType::direct(t, None, None, attr)
+ }
};
arg_tys.push(ty);
}
use lib::llvm::{llvm, Integer, Pointer, Float, Double};
use lib::llvm::{Struct, Array, Attribute};
-use lib::llvm::{StructRetAttribute, ByValAttribute};
+use lib::llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
use middle::trans::cabi::*;
use middle::trans::context::CrateContext;
use middle::trans::type_::Type;
fn x86_64_ty(ccx: &CrateContext,
ty: Type,
is_mem_cls: |cls: &[RegClass]| -> bool,
- attr: Attribute)
+ ind_attr: Attribute)
-> ArgType {
if !ty.is_reg_ty() {
let cls = classify_ty(ty);
if is_mem_cls(cls.as_slice()) {
- ArgType::indirect(ty, Some(attr))
+ ArgType::indirect(ty, Some(ind_attr))
} else {
ArgType::direct(ty,
Some(llreg_ty(ccx, cls.as_slice())),
None)
}
} else {
- ArgType::direct(ty, None, None, None)
+ let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ ArgType::direct(ty, None, None, attr)
}
}
param_bounds.get(n_bound).clone()
}
-// Casts a Rust bool value to an i1.
-pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef {
- build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(bcx.ccx(), false))
-}
-
pub fn langcall(bcx: &Block,
span: Option<Span>,
msg: &str,
let (dv, _dt) = const_deref(cx, te, ty, true);
dv
}
- ast::UnNot => {
- match ty::get(ty).sty {
- ty::ty_bool => {
- // Somewhat questionable, but I believe this is
- // correct.
- let te = llvm::LLVMConstTrunc(te, Type::i1(cx).to_ref());
- let te = llvm::LLVMConstNot(te);
- llvm::LLVMConstZExt(te, Type::bool(cx).to_ref())
- }
- _ => llvm::LLVMConstNot(te),
- }
- }
+ ast::UnNot => llvm::LLVMConstNot(te),
ast::UnNeg => {
if is_float { llvm::LLVMConstFNeg(te) }
else { llvm::LLVMConstNeg(te) }
if type_is_zero_size(bcx.ccx(), ty) {
C_undef(type_of::type_of(bcx.ccx(), ty))
- } else if ty::type_is_bool(ty) {
- LoadRangeAssert(bcx, llptr, 0, 2, lib::llvm::False)
} else if ty::type_is_char(ty) {
// a char is a unicode codepoint, and so takes values from 0
// to 0x10FFFF inclusive only.
pub fn to_llbool<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
assert!(ty::type_is_bool(self.ty) || ty::type_is_bot(self.ty))
- let cond_val = self.to_llscalarish(bcx);
- bool_to_i1(bcx, cond_val)
+ self.to_llscalarish(bcx)
}
}
let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
let llresult = if ty::type_is_bool(un_ty) {
let val = datum.to_llscalarish(bcx);
- let llcond = ICmp(bcx,
- lib::llvm::IntEQ,
- val,
- C_bool(ccx, false));
- Select(bcx, llcond, C_bool(ccx, true), C_bool(ccx, false))
+ Xor(bcx, val, C_bool(ccx, true))
} else {
// Note: `Not` is bitwise, not suitable for logical not.
Not(bcx, datum.to_llscalarish(bcx))
if ty::type_is_bot(rhs_t) {
C_bool(bcx.ccx(), false)
} else if ty::type_is_scalar(rhs_t) {
- let cmpr = base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op);
- bcx = cmpr.bcx;
- ZExt(bcx, cmpr.val, Type::i8(bcx.ccx()))
+ unpack_result!(bcx, base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op))
} else if is_simd {
base::compare_simd_types(bcx, lhs, rhs, intype, ty::simd_size(tcx, lhs_t), op)
} else {
let join = fcx.new_id_block("join", binop_expr.id);
let before_rhs = fcx.new_id_block("before_rhs", b.id);
- let lhs_i1 = bool_to_i1(past_lhs, lhs);
match op {
- lazy_and => CondBr(past_lhs, lhs_i1, before_rhs.llbb, join.llbb),
- lazy_or => CondBr(past_lhs, lhs_i1, join.llbb, before_rhs.llbb)
+ lazy_and => CondBr(past_lhs, lhs, before_rhs.llbb, join.llbb),
+ lazy_or => CondBr(past_lhs, lhs, join.llbb, before_rhs.llbb)
}
let DatumBlock {bcx: past_rhs, datum: rhs} = trans(before_rhs, b);
let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
let llfn = bcx.ccx().get_intrinsic(&name);
- // convert `i1` to a `bool`, and write to the out parameter
let val = Call(bcx, llfn, [a, b], []);
- let result = ExtractValue(bcx, val, 0);
- let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
- let ret = C_undef(type_of::type_of(bcx.ccx(), t));
- let ret = InsertValue(bcx, ret, result, 0);
- let ret = InsertValue(bcx, ret, overflow, 1);
if type_is_immediate(bcx.ccx(), t) {
- Ret(bcx, ret);
+ Ret(bcx, val);
} else {
let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
- Store(bcx, ret, retptr);
+ Store(bcx, val, retptr);
RetVoid(bcx);
}
}
mth_idx,
v),
ArgVals(args), None));
- let result = bool_to_i1(bcx, result);
let next_bcx = fcx.new_temp_block("next");
CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
self.bcx = next_bcx
}
pub fn bool(ccx: &CrateContext) -> Type {
- Type::i8(ccx)
+ Type::i1(ccx)
}
pub fn char(ccx: &CrateContext) -> Type {