Skip to content

Commit 1291cc2

Browse files
committed
Groundwork for structural comparison. Still lacking the actual loop that does it.
1 parent 86309ed commit 1291cc2

File tree

2 files changed

+118
-26
lines changed

2 files changed

+118
-26
lines changed

src/comp/lib/llvm.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,25 @@ const uint LLVMIntSLT = 40u;
7676
const uint LLVMIntSLE = 41u;
7777

7878

79+
// Consts for the LLVM RealPredicate type, pre-case to uint.
80+
// FIXME: as above.
81+
82+
const uint LLVMRealOEQ = 1u;
83+
const uint LLVMRealOGT = 2u;
84+
const uint LLVMRealOGE = 3u;
85+
const uint LLVMRealOLT = 4u;
86+
const uint LLVMRealOLE = 5u;
87+
const uint LLVMRealONE = 6u;
88+
89+
const uint LLVMRealORD = 7u;
90+
const uint LLVMRealUNO = 8u;
91+
const uint LLVMRealUEQ = 9u;
92+
const uint LLVMRealUGT = 10u;
93+
const uint LLVMRealUGE = 11u;
94+
const uint LLVMRealULT = 12u;
95+
const uint LLVMRealULE = 13u;
96+
const uint LLVMRealUNE = 14u;
97+
7998
native mod llvm = llvm_lib {
8099

81100
type ModuleRef;
@@ -657,7 +676,7 @@ native mod llvm = llvm_lib {
657676
fn LLVMBuildICmp(BuilderRef B, uint Op,
658677
ValueRef LHS, ValueRef RHS,
659678
sbuf Name) -> ValueRef;
660-
fn LLVMBuildFCmp(BuilderRef B, RealPredicate Op,
679+
fn LLVMBuildFCmp(BuilderRef B, uint Op,
661680
ValueRef LHS, ValueRef RHS,
662681
sbuf Name) -> ValueRef;
663682

@@ -1034,7 +1053,7 @@ obj builder(BuilderRef B) {
10341053
ret llvm.LLVMBuildICmp(B, Op, LHS, RHS, _str.buf(""));
10351054
}
10361055

1037-
fn FCmp(RealPredicate Op, ValueRef LHS, ValueRef RHS) -> ValueRef {
1056+
fn FCmp(uint Op, ValueRef LHS, ValueRef RHS) -> ValueRef {
10381057
ret llvm.LLVMBuildFCmp(B, Op, LHS, RHS, _str.buf(""));
10391058
}
10401059

src/comp/middle/trans.rs

Lines changed: 97 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,10 +1958,66 @@ fn trans_unary(@block_ctxt cx, ast.unop op,
19581958
fail;
19591959
}
19601960

1961-
// FIXME: implement proper structural comparison.
1961+
fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t,
1962+
ValueRef lhs, ValueRef rhs) -> result {
1963+
1964+
if (ty.type_is_scalar(t)) {
1965+
ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs));
1966+
1967+
} else if (ty.type_is_structural(t)) {
1968+
auto scx = new_sub_block_ctxt(cx, "structural compare body");
1969+
auto next = new_sub_block_ctxt(cx, "structural compare completion");
1970+
cx.build.Br(scx.llbb);
1971+
1972+
// Start with the assumptioin that our predicate holds.
1973+
auto flag = scx.build.Alloca(T_i1());
1974+
scx.build.Store(C_integral(1, T_i1()), flag);
1975+
1976+
// Attempt to prove otherwise by inverting the sense of the comparison
1977+
// on each inner element and bailing if any succeed.
1978+
1979+
// FIXME: finish this.
1980+
1981+
auto v = scx.build.Load(flag);
1982+
scx.build.Br(next.llbb);
1983+
ret res(next, v);
1984+
1985+
} else {
1986+
// FIXME: compare vec, str, box?
1987+
cx.fcx.ccx.sess.unimpl("type in trans_compare");
1988+
ret res(cx, C_bool(false));
1989+
}
1990+
}
1991+
1992+
fn trans_scalar_compare(@block_ctxt cx, ast.binop op, @ty.t t,
1993+
ValueRef lhs, ValueRef rhs) -> ValueRef {
1994+
if (ty.type_is_fp(t)) {
1995+
ret trans_fp_compare(cx, op, t, lhs, rhs);
1996+
} else {
1997+
ret trans_integral_compare(cx, op, t, lhs, rhs);
1998+
}
1999+
}
2000+
2001+
fn trans_fp_compare(@block_ctxt cx, ast.binop op, @ty.t fptype,
2002+
ValueRef lhs, ValueRef rhs) -> ValueRef {
19622003

1963-
fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype,
1964-
ValueRef lhs, ValueRef rhs) -> ValueRef {
2004+
auto cmp = lib.llvm.LLVMIntEQ;
2005+
alt (op) {
2006+
// FIXME: possibly use the unordered-or-< predicates here,
2007+
// for now we're only going with ordered-and-< style (no NaNs).
2008+
case (ast.eq) { cmp = lib.llvm.LLVMRealOEQ; }
2009+
case (ast.ne) { cmp = lib.llvm.LLVMRealONE; }
2010+
case (ast.lt) { cmp = lib.llvm.LLVMRealOLT; }
2011+
case (ast.gt) { cmp = lib.llvm.LLVMRealOGT; }
2012+
case (ast.le) { cmp = lib.llvm.LLVMRealOLE; }
2013+
case (ast.ge) { cmp = lib.llvm.LLVMRealOGE; }
2014+
}
2015+
2016+
ret cx.build.FCmp(cmp, lhs, rhs);
2017+
}
2018+
2019+
fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype,
2020+
ValueRef lhs, ValueRef rhs) -> ValueRef {
19652021
auto cmp = lib.llvm.LLVMIntEQ;
19662022
alt (op) {
19672023
case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; }
@@ -2000,34 +2056,34 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype,
20002056
}
20012057

20022058
fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype,
2003-
ValueRef lhs, ValueRef rhs) -> ValueRef {
2059+
ValueRef lhs, ValueRef rhs) -> result {
20042060

20052061
alt (op) {
2006-
case (ast.add) { ret cx.build.Add(lhs, rhs); }
2007-
case (ast.sub) { ret cx.build.Sub(lhs, rhs); }
2062+
case (ast.add) { ret res(cx, cx.build.Add(lhs, rhs)); }
2063+
case (ast.sub) { ret res(cx, cx.build.Sub(lhs, rhs)); }
20082064

2009-
case (ast.mul) { ret cx.build.Mul(lhs, rhs); }
2065+
case (ast.mul) { ret res(cx, cx.build.Mul(lhs, rhs)); }
20102066
case (ast.div) {
20112067
if (ty.type_is_signed(intype)) {
2012-
ret cx.build.SDiv(lhs, rhs);
2068+
ret res(cx, cx.build.SDiv(lhs, rhs));
20132069
} else {
2014-
ret cx.build.UDiv(lhs, rhs);
2070+
ret res(cx, cx.build.UDiv(lhs, rhs));
20152071
}
20162072
}
20172073
case (ast.rem) {
20182074
if (ty.type_is_signed(intype)) {
2019-
ret cx.build.SRem(lhs, rhs);
2075+
ret res(cx, cx.build.SRem(lhs, rhs));
20202076
} else {
2021-
ret cx.build.URem(lhs, rhs);
2077+
ret res(cx, cx.build.URem(lhs, rhs));
20222078
}
20232079
}
20242080

2025-
case (ast.bitor) { ret cx.build.Or(lhs, rhs); }
2026-
case (ast.bitand) { ret cx.build.And(lhs, rhs); }
2027-
case (ast.bitxor) { ret cx.build.Xor(lhs, rhs); }
2028-
case (ast.lsl) { ret cx.build.Shl(lhs, rhs); }
2029-
case (ast.lsr) { ret cx.build.LShr(lhs, rhs); }
2030-
case (ast.asr) { ret cx.build.AShr(lhs, rhs); }
2081+
case (ast.bitor) { ret res(cx, cx.build.Or(lhs, rhs)); }
2082+
case (ast.bitand) { ret res(cx, cx.build.And(lhs, rhs)); }
2083+
case (ast.bitxor) { ret res(cx, cx.build.Xor(lhs, rhs)); }
2084+
case (ast.lsl) { ret res(cx, cx.build.Shl(lhs, rhs)); }
2085+
case (ast.lsr) { ret res(cx, cx.build.LShr(lhs, rhs)); }
2086+
case (ast.asr) { ret res(cx, cx.build.AShr(lhs, rhs)); }
20312087
case (_) {
20322088
ret trans_compare(cx, op, intype, lhs, rhs);
20332089
}
@@ -2055,6 +2111,21 @@ fn autoderef(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
20552111
}
20562112
}
20572113

2114+
fn autoderefed_ty(@ty.t t) -> @ty.t {
2115+
let @ty.t t1 = t;
2116+
2117+
while (true) {
2118+
alt (t1.struct) {
2119+
case (ty.ty_box(?inner)) {
2120+
t1 = inner;
2121+
}
2122+
case (_) {
2123+
ret t1;
2124+
}
2125+
}
2126+
}
2127+
}
2128+
20582129
fn trans_binary(@block_ctxt cx, ast.binop op,
20592130
@ast.expr a, @ast.expr b) -> result {
20602131

@@ -2109,8 +2180,9 @@ fn trans_binary(@block_ctxt cx, ast.binop op,
21092180
auto rhs = trans_expr(lhs.bcx, b);
21102181
auto rhty = ty.expr_ty(b);
21112182
rhs = autoderef(rhs.bcx, rhs.val, rhty);
2112-
ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty,
2113-
lhs.val, rhs.val));
2183+
ret trans_eager_binop(rhs.bcx, op,
2184+
autoderefed_ty(lhty),
2185+
lhs.val, rhs.val);
21142186
}
21152187
}
21162188
fail;
@@ -2399,8 +2471,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
23992471
auto lltype = ty.ann_to_type(ann);
24002472
auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit);
24012473

2402-
auto matched_cx = new_sub_block_ctxt(cx, "matched_cx");
2403-
cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
2474+
auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx");
2475+
lleq.bcx.build.CondBr(lleq.val, matched_cx.llbb, next_cx.llbb);
24042476
ret res(matched_cx, llval);
24052477
}
24062478

@@ -2656,8 +2728,9 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
26562728
fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
26572729
&ast.ident field, &ast.ann ann) -> lval_result {
26582730
auto r = trans_expr(cx, base);
2659-
r = autoderef(r.bcx, r.val, ty.expr_ty(base));
26602731
auto t = ty.expr_ty(base);
2732+
r = autoderef(r.bcx, r.val, t);
2733+
t = autoderefed_ty(t);
26612734
alt (t.struct) {
26622735
case (ty.ty_tup(?fields)) {
26632736
let uint ix = ty.field_num(cx.fcx.ccx.sess, sp, field);
@@ -3439,8 +3512,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
34393512
auto v = trans_eager_binop(rhs_res.bcx, op, t,
34403513
lhs_val, rhs_res.val);
34413514
// FIXME: calculate copy init-ness in typestate.
3442-
ret copy_ty(rhs_res.bcx, DROP_EXISTING,
3443-
lhs_res.res.val, v, t);
3515+
ret copy_ty(v.bcx, DROP_EXISTING,
3516+
lhs_res.res.val, v.val, t);
34443517
}
34453518

34463519
case (ast.expr_bind(?f, ?args, ?ann)) {

0 commit comments

Comments
 (0)