Skip to content

More ergonomic multiple-data expressions. #12917

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@
################################################################################

TARGET_CRATES := std extra green rustuv native flate arena glob term semver \
uuid serialize sync getopts collections num test time rand
HOST_CRATES := syntax rustc rustdoc fourcc hexfloat
uuid serialize sync getopts collections num test time rand \
simd
HOST_CRATES := syntax rustc rustdoc fourcc hexfloat simd_syntax
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc

Expand Down Expand Up @@ -81,6 +82,8 @@ DEPS_num := std rand
DEPS_test := std extra collections getopts serialize term
DEPS_time := std serialize
DEPS_rand := std
DEPS_simd := std simd_syntax
DEPS_simd_syntax := syntax std

TOOL_DEPS_compiletest := test green rustuv getopts
TOOL_DEPS_rustdoc := rustdoc native
Expand Down
16 changes: 16 additions & 0 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,22 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
assert_eq!(next(st), ']');
return ty::mk_struct(st.tcx, did, substs);
}
'S' => {
assert_eq!(next(st), '[');
let prim_ty = parse_ty(st, |x, y| conv(x, y) );
if !ty::type_is_simd_scalar(st.tcx, prim_ty) {
error!("invalid type in simd: {}", ::util::ppaux::ty_to_str(st.tcx, prim_ty));
fail!();
}
assert_eq!(next(st), 'x');
let count = parse_uint(st);
if count == 0 {
error!("invalid simd element count: {}", count);
fail!();
}
assert_eq!(next(st), ']');
return ty::mk_simd(st.tcx, prim_ty, count);
}
c => { error!("unexpected char in type string: {}", c); fail!();}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,11 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_simd(t, n) => {
mywrite!(w, "S[");
enc_ty(w, cx, t);
mywrite!(w, "x{}]", n);
}
ty::ty_err => fail!("shouldn't encode error type")
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/librustc/middle/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use middle::cfg::*;
use middle::graph;
use middle::typeck;
use middle::ty;
use std::vec;
use std::vec_ng::Vec;
use syntax::ast;
use syntax::ast_util;
Expand Down Expand Up @@ -370,7 +371,7 @@ impl CFGBuilder {
self.call(expr, pred, e, [])
}

ast::ExprTup(ref exprs) => {
ast::ExprTup(ref exprs) | ast::ExprSimd(ref exprs) => {
self.straightline(expr, pred, exprs.as_slice())
}

Expand All @@ -380,6 +381,14 @@ impl CFGBuilder {
fields.iter().map(|f| f.expr).collect();
self.straightline(expr, base_exit, field_exprs.as_slice())
}
ast::ExprSwizzle(left, opt_right, ref mask) => {
let exprs = vec::build(Some(3), |push| {
push(left);
opt_right.iter().advance(|&r| { push(r); true });
mask.iter().advance(|&m| { push(m); true });
});
self.straightline(expr, pred, exprs)
}

ast::ExprRepeat(elem, count, _) => {
self.straightline(expr, pred, [elem, count])
Expand Down
50 changes: 50 additions & 0 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,3 +551,53 @@ pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: &Expr, b: &Expr) -> Option<bool> {
pub fn lit_eq(a: &Lit, b: &Lit) -> Option<bool> {
compare_const_vals(&lit_to_const(a), &lit_to_const(b)).map(|val| val == 0)
}

// Returns the evaluated positive integer for the provided expression, or reports error
pub fn eval_positive_integer<T: ty::ExprTyProvider>(tcx: &T,
count_expr: &ast::Expr,
msg: &str) -> uint {
match eval_const_expr_partial(tcx, count_expr) {
Ok(ref const_val) => match *const_val {
const_int(count) => if count < 0 {
tcx.ty_ctxt().sess.span_err(count_expr.span,
format!("expected positive integer for \
{:s} but found negative integer",
msg));
return 0;
} else {
return count as uint
},
const_uint(count) => return count as uint,
const_float(count) => {
tcx.ty_ctxt().sess.span_err(count_expr.span,
format!("expected positive integer for \
{:s} but found float", msg));
return count as uint;
}
const_str(_) => {
tcx.ty_ctxt().sess.span_err(count_expr.span,
format!("expected positive integer for \
{:s} but found string", msg));
return 0;
}
const_bool(_) => {
tcx.ty_ctxt().sess.span_err(count_expr.span,
format!("expected positive integer for \
{:s} but found boolean", msg));
return 0;
}
const_binary(_) => {
tcx.ty_ctxt().sess.span_err(count_expr.span,
format!("expected positive integer for \
{:s} but found binary array", msg));
return 0;
}
},
Err(..) => {
tcx.ty_ctxt().sess.span_err(count_expr.span,
format!("expected constant integer for {:s} \
but found variable", msg));
return 0;
}
}
}
7 changes: 6 additions & 1 deletion src/librustc/middle/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,9 +597,14 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
self.walk_call(expr.id, [e], in_out, loop_scopes);
}

ast::ExprTup(ref exprs) => {
ast::ExprTup(ref exprs) | ast::ExprSimd(ref exprs) => {
self.walk_exprs(exprs.as_slice(), in_out, loop_scopes);
}
ast::ExprSwizzle(left, opt_right, ref mask) => {
self.walk_expr(left, in_out, loop_scopes);
self.walk_opt_expr(opt_right, in_out, loop_scopes);
self.walk_exprs(mask.as_slice(), in_out, loop_scopes);
}

ast::ExprBinary(op, l, r) if ast_util::lazy_binop(op) => {
self.walk_expr(l, in_out, loop_scopes);
Expand Down
13 changes: 10 additions & 3 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@ fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
ExprAgain(_) | ExprLit(_) | ExprRet(..) | ExprBlock(..) |
ExprAssign(..) | ExprAssignOp(..) | ExprMac(..) |
ExprStruct(..) | ExprRepeat(..) | ExprParen(..) |
ExprInlineAsm(..) | ExprBox(..) => {
ExprInlineAsm(..) | ExprBox(..) | ExprSwizzle(..) |
ExprSimd(..) => {
visit::walk_expr(v, expr, this);
}
}
Expand Down Expand Up @@ -1211,6 +1212,12 @@ impl Liveness {
self.propagate_through_expr(field.expr, succ)
})
}
ExprSwizzle(left, opt_right, _) => {
// no need to propagate through the mask;
// it has to be a constant expresssion
let succ = self.propagate_through_expr(left, succ);
self.propagate_through_opt_expr(opt_right, succ)
}

ExprCall(f, ref args) => {
// calling a fn with bot return type means that the fn
Expand All @@ -1231,7 +1238,7 @@ impl Liveness {
self.propagate_through_exprs(args.as_slice(), succ)
}

ExprTup(ref exprs) => {
ExprTup(ref exprs) | ExprSimd(ref exprs) => {
self.propagate_through_exprs(exprs.as_slice(), succ)
}

Expand Down Expand Up @@ -1527,7 +1534,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
ExprParen(..) | ExprFnBlock(..) | ExprProc(..) | ExprPath(..) |
ExprBox(..) => {
ExprBox(..) | ExprSwizzle(..) | ExprSimd(..) => {
visit::walk_expr(this, expr, ());
}
ExprForLoop(..) => fail!("non-desugared expr_for_loop")
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
}

ty::ty_vec(_, ty::vstore_fixed(_)) |
ty::ty_str(ty::vstore_fixed(_)) => {
ty::ty_str(ty::vstore_fixed(_)) | ty::ty_simd(..) => {
Some(deref_interior(InteriorElement(element_kind(t))))
}

Expand Down Expand Up @@ -473,7 +473,8 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
ast::ExprLit(..) | ast::ExprBreak(..) | ast::ExprMac(..) |
ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
ast::ExprInlineAsm(..) | ast::ExprBox(..) => {
ast::ExprInlineAsm(..) | ast::ExprBox(..) | ast::ExprSwizzle(..) |
ast::ExprSimd(..) => {
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
}

Expand Down Expand Up @@ -814,7 +815,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
//! - `derefs`: the deref number to be used for
//! the implicit index deref, if any (see above)

let element_ty = match ty::index(base_cmt.ty) {
let element_ty = match ty::index(self.tcx(), base_cmt.ty) {
Some(ref mt) => mt.ty,
None => {
self.tcx().sess.span_bug(
Expand Down
9 changes: 8 additions & 1 deletion src/librustc/middle/moves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,15 @@ impl VisitContext {
}
}
}
ExprSwizzle(left_expr, opt_right_expr, _) => {
self.consume_expr(left_expr);
match opt_right_expr {
Some(r) => self.consume_expr(r),
None => {}
}
}

ExprTup(ref exprs) => {
ExprTup(ref exprs) | ExprSimd(ref exprs) => {
self.consume_exprs(exprs.as_slice());
}

Expand Down
30 changes: 25 additions & 5 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,9 +581,19 @@ pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
}
}


// Used only for creating scalar comparison glue.
pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
pub enum inner_vector_type {
vsigned_int,
vunsigned_int,
vfloating_point
}
pub enum scalar_type {
nil_type,
signed_int,
unsigned_int,
floating_point,
vector_type(inner_vector_type),
}

// NB: This produces an i1, not a Rust bool (i8).
pub fn compare_scalar_types<'a>(
Expand All @@ -601,6 +611,16 @@ pub fn compare_scalar_types<'a>(
ty::ty_uint(_) | ty::ty_char => f(unsigned_int),
ty::ty_int(_) => f(signed_int),
ty::ty_float(_) => f(floating_point),
ty::ty_simd(..) => {
match ty::get(ty::simd_type(cx.tcx(), t)).sty {
ty::ty_bool | ty::ty_ptr(_) | ty::ty_uint(..) => {
f(vector_type(vunsigned_int))
}
ty::ty_int(..) => f(vector_type(vsigned_int)),
ty::ty_float(..) => f(vector_type(vfloating_point)),
_ => unreachable!(),
}
}
// Should never get here, because t is scalar.
_ => cx.sess().bug("non-scalar type passed to compare_scalar_types")
}
Expand Down Expand Up @@ -631,7 +651,7 @@ pub fn compare_scalar_values<'a>(
_ => die(cx)
}
}
floating_point => {
floating_point | vector_type(vfloating_point) => {
let cmp = match op {
ast::BiEq => lib::llvm::RealOEQ,
ast::BiNe => lib::llvm::RealUNE,
Expand All @@ -643,7 +663,7 @@ pub fn compare_scalar_values<'a>(
};
return FCmp(cx, cmp, lhs, rhs);
}
signed_int => {
signed_int | vector_type(vsigned_int) => {
let cmp = match op {
ast::BiEq => lib::llvm::IntEQ,
ast::BiNe => lib::llvm::IntNE,
Expand All @@ -655,7 +675,7 @@ pub fn compare_scalar_values<'a>(
};
return ICmp(cx, cmp, lhs, rhs);
}
unsigned_int => {
unsigned_int | vector_type(vunsigned_int) => {
let cmp = match op {
ast::BiEq => lib::llvm::IntEQ,
ast::BiNe => lib::llvm::IntNE,
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,11 @@ pub fn C_bytes(bytes: &[u8]) -> ValueRef {
return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint, True);
}
}
pub fn C_vector(elts: &[ValueRef]) -> ValueRef {
unsafe {
llvm::LLVMConstVector(elts.as_ptr(), elts.len() as u32)
}
}

pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
unsafe {
Expand Down
10 changes: 7 additions & 3 deletions src/librustc/middle/trans/datum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use middle::trans::glue;
use middle::trans::tvec;
use middle::trans::type_of;
use middle::trans::write_guard;
use middle::trans::simd;
use middle::ty;
use util::ppaux::{ty_to_str};

Expand Down Expand Up @@ -529,9 +530,12 @@ impl Datum<Lvalue> {
}

pub fn get_vec_base_and_len<'a>(&self, bcx: &'a Block<'a>) -> (ValueRef, ValueRef) {
//! Converts a vector into the slice pair.

tvec::get_base_and_len(bcx, self.val, self.ty)
//! Converts a vector or a simd into the slice pair.
if ty::type_is_simd(bcx.ccx().tcx, self.ty) {
simd::get_base_and_len(bcx, self.val, self.ty)
} else {
tvec::get_base_and_len(bcx, self.val, self.ty)
}
}
}

Expand Down
30 changes: 22 additions & 8 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2129,15 +2129,14 @@ fn type_metadata(cx: &CrateContext,
ty::ty_trait(def_id, ref substs, trait_store, mutability, ref bounds) => {
trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
},
ty::ty_struct(def_id, ref substs) => {
if ty::type_is_simd(cx.tcx, t) {
let element_type = ty::simd_type(cx.tcx, t);
let len = ty::simd_size(cx.tcx, t);
fixed_vec_metadata(cx, element_type, len, usage_site_span)
} else {
prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
}
ty::ty_struct(def_id, ref substs) if !ty::type_is_simd(cx.tcx, t) => {
prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
},
_ if ty::type_is_simd(cx.tcx, t) => {
let element_type = ty::simd_type(cx.tcx, t);
let len = ty::simd_size(cx.tcx, t);
fixed_vec_metadata(cx, element_type, len, usage_site_span)
}
ty::ty_tup(ref elements) => {
prepare_tuple_metadata(cx,
t,
Expand Down Expand Up @@ -2578,6 +2577,21 @@ fn populate_scope_map(cx: &CrateContext,
walk_expr(cx, *ie, scope_stack, scope_map);
}
}
ast::ExprSimd(ref exprs) => {
for &e in exprs.iter() {
walk_expr(cx, e, scope_stack, scope_map);
}
}
ast::ExprSwizzle(left, opt_right, _) => {
walk_expr(cx, left, scope_stack, scope_map);
match opt_right {
Some(right) => {
walk_expr(cx, right, scope_stack, scope_map);
}
None => {}
};
// mask is a constant expression, so skip.
}

ast::ExprAssign(sub_exp1, sub_exp2) |
ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
Expand Down
Loading