diff options
| author | Graydon Hoare <[email protected]> | 2011-02-28 16:36:08 -0800 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-02-28 16:36:14 -0800 |
| commit | 1291cc2df90c36eee8642048e1bf1b69a690781f (patch) | |
| tree | bfa8087261a509a81cce8edaebcee4afd170a01f | |
| parent | rustc: Write tag variant discriminants into the crate as integer constants (diff) | |
| download | rust-1291cc2df90c36eee8642048e1bf1b69a690781f.tar.xz rust-1291cc2df90c36eee8642048e1bf1b69a690781f.zip | |
Groundwork for structural comparison. Still lacking the actual loop that does it.
| -rw-r--r-- | src/comp/lib/llvm.rs | 23 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 121 |
2 files changed, 118 insertions, 26 deletions
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 751507d6..f75bdbe1 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -76,6 +76,25 @@ const uint LLVMIntSLT = 40u; const uint LLVMIntSLE = 41u; +// Consts for the LLVM RealPredicate type, pre-case to uint. +// FIXME: as above. + +const uint LLVMRealOEQ = 1u; +const uint LLVMRealOGT = 2u; +const uint LLVMRealOGE = 3u; +const uint LLVMRealOLT = 4u; +const uint LLVMRealOLE = 5u; +const uint LLVMRealONE = 6u; + +const uint LLVMRealORD = 7u; +const uint LLVMRealUNO = 8u; +const uint LLVMRealUEQ = 9u; +const uint LLVMRealUGT = 10u; +const uint LLVMRealUGE = 11u; +const uint LLVMRealULT = 12u; +const uint LLVMRealULE = 13u; +const uint LLVMRealUNE = 14u; + native mod llvm = llvm_lib { type ModuleRef; @@ -657,7 +676,7 @@ native mod llvm = llvm_lib { fn LLVMBuildICmp(BuilderRef B, uint Op, ValueRef LHS, ValueRef RHS, sbuf Name) -> ValueRef; - fn LLVMBuildFCmp(BuilderRef B, RealPredicate Op, + fn LLVMBuildFCmp(BuilderRef B, uint Op, ValueRef LHS, ValueRef RHS, sbuf Name) -> ValueRef; @@ -1034,7 +1053,7 @@ obj builder(BuilderRef B) { ret llvm.LLVMBuildICmp(B, Op, LHS, RHS, _str.buf("")); } - fn FCmp(RealPredicate Op, ValueRef LHS, ValueRef RHS) -> ValueRef { + fn FCmp(uint Op, ValueRef LHS, ValueRef RHS) -> ValueRef { ret llvm.LLVMBuildFCmp(B, Op, LHS, RHS, _str.buf("")); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b2ef0f16..4a45beea 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1958,10 +1958,66 @@ fn trans_unary(@block_ctxt cx, ast.unop op, fail; } -// FIXME: implement proper structural comparison. +fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + + if (ty.type_is_scalar(t)) { + ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs)); + + } else if (ty.type_is_structural(t)) { + auto scx = new_sub_block_ctxt(cx, "structural compare body"); + auto next = new_sub_block_ctxt(cx, "structural compare completion"); + cx.build.Br(scx.llbb); + + // Start with the assumptioin that our predicate holds. + auto flag = scx.build.Alloca(T_i1()); + scx.build.Store(C_integral(1, T_i1()), flag); + + // Attempt to prove otherwise by inverting the sense of the comparison + // on each inner element and bailing if any succeed. + + // FIXME: finish this. + + auto v = scx.build.Load(flag); + scx.build.Br(next.llbb); + ret res(next, v); + + } else { + // FIXME: compare vec, str, box? + cx.fcx.ccx.sess.unimpl("type in trans_compare"); + ret res(cx, C_bool(false)); + } +} + +fn trans_scalar_compare(@block_ctxt cx, ast.binop op, @ty.t t, + ValueRef lhs, ValueRef rhs) -> ValueRef { + if (ty.type_is_fp(t)) { + ret trans_fp_compare(cx, op, t, lhs, rhs); + } else { + ret trans_integral_compare(cx, op, t, lhs, rhs); + } +} + +fn trans_fp_compare(@block_ctxt cx, ast.binop op, @ty.t fptype, + ValueRef lhs, ValueRef rhs) -> ValueRef { -fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, - ValueRef lhs, ValueRef rhs) -> ValueRef { + auto cmp = lib.llvm.LLVMIntEQ; + alt (op) { + // FIXME: possibly use the unordered-or-< predicates here, + // for now we're only going with ordered-and-< style (no NaNs). + case (ast.eq) { cmp = lib.llvm.LLVMRealOEQ; } + case (ast.ne) { cmp = lib.llvm.LLVMRealONE; } + case (ast.lt) { cmp = lib.llvm.LLVMRealOLT; } + case (ast.gt) { cmp = lib.llvm.LLVMRealOGT; } + case (ast.le) { cmp = lib.llvm.LLVMRealOLE; } + case (ast.ge) { cmp = lib.llvm.LLVMRealOGE; } + } + + ret cx.build.FCmp(cmp, lhs, rhs); +} + +fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype, + ValueRef lhs, ValueRef rhs) -> ValueRef { auto cmp = lib.llvm.LLVMIntEQ; alt (op) { case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } @@ -2000,34 +2056,34 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, } fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, - ValueRef lhs, ValueRef rhs) -> ValueRef { + ValueRef lhs, ValueRef rhs) -> result { alt (op) { - case (ast.add) { ret cx.build.Add(lhs, rhs); } - case (ast.sub) { ret cx.build.Sub(lhs, rhs); } + case (ast.add) { ret res(cx, cx.build.Add(lhs, rhs)); } + case (ast.sub) { ret res(cx, cx.build.Sub(lhs, rhs)); } - case (ast.mul) { ret cx.build.Mul(lhs, rhs); } + case (ast.mul) { ret res(cx, cx.build.Mul(lhs, rhs)); } case (ast.div) { if (ty.type_is_signed(intype)) { - ret cx.build.SDiv(lhs, rhs); + ret res(cx, cx.build.SDiv(lhs, rhs)); } else { - ret cx.build.UDiv(lhs, rhs); + ret res(cx, cx.build.UDiv(lhs, rhs)); } } case (ast.rem) { if (ty.type_is_signed(intype)) { - ret cx.build.SRem(lhs, rhs); + ret res(cx, cx.build.SRem(lhs, rhs)); } else { - ret cx.build.URem(lhs, rhs); + ret res(cx, cx.build.URem(lhs, rhs)); } } - case (ast.bitor) { ret cx.build.Or(lhs, rhs); } - case (ast.bitand) { ret cx.build.And(lhs, rhs); } - case (ast.bitxor) { ret cx.build.Xor(lhs, rhs); } - case (ast.lsl) { ret cx.build.Shl(lhs, rhs); } - case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } - case (ast.asr) { ret cx.build.AShr(lhs, rhs); } + case (ast.bitor) { ret res(cx, cx.build.Or(lhs, rhs)); } + case (ast.bitand) { ret res(cx, cx.build.And(lhs, rhs)); } + case (ast.bitxor) { ret res(cx, cx.build.Xor(lhs, rhs)); } + case (ast.lsl) { ret res(cx, cx.build.Shl(lhs, rhs)); } + case (ast.lsr) { ret res(cx, cx.build.LShr(lhs, rhs)); } + case (ast.asr) { ret res(cx, cx.build.AShr(lhs, rhs)); } case (_) { ret trans_compare(cx, op, intype, lhs, rhs); } @@ -2055,6 +2111,21 @@ fn autoderef(@block_ctxt cx, ValueRef v, @ty.t t) -> result { } } +fn autoderefed_ty(@ty.t t) -> @ty.t { + let @ty.t t1 = t; + + while (true) { + alt (t1.struct) { + case (ty.ty_box(?inner)) { + t1 = inner; + } + case (_) { + ret t1; + } + } + } +} + fn trans_binary(@block_ctxt cx, ast.binop op, @ast.expr a, @ast.expr b) -> result { @@ -2109,8 +2180,9 @@ fn trans_binary(@block_ctxt cx, ast.binop op, auto rhs = trans_expr(lhs.bcx, b); auto rhty = ty.expr_ty(b); rhs = autoderef(rhs.bcx, rhs.val, rhty); - ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty, - lhs.val, rhs.val)); + ret trans_eager_binop(rhs.bcx, op, + autoderefed_ty(lhty), + lhs.val, rhs.val); } } fail; @@ -2399,8 +2471,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, auto lltype = ty.ann_to_type(ann); auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit); - auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); - cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); + auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx"); + lleq.bcx.build.CondBr(lleq.val, matched_cx.llbb, next_cx.llbb); ret res(matched_cx, llval); } @@ -2656,8 +2728,9 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base, &ast.ident field, &ast.ann ann) -> lval_result { auto r = trans_expr(cx, base); - r = autoderef(r.bcx, r.val, ty.expr_ty(base)); auto t = ty.expr_ty(base); + r = autoderef(r.bcx, r.val, t); + t = autoderefed_ty(t); alt (t.struct) { case (ty.ty_tup(?fields)) { 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 { auto v = trans_eager_binop(rhs_res.bcx, op, t, lhs_val, rhs_res.val); // FIXME: calculate copy init-ness in typestate. - ret copy_ty(rhs_res.bcx, DROP_EXISTING, - lhs_res.res.val, v, t); + ret copy_ty(v.bcx, DROP_EXISTING, + lhs_res.res.val, v.val, t); } case (ast.expr_bind(?f, ?args, ?ann)) { |