]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/_match.rs
13104cfa40ae718854058517891c9fb13408f447
[rust.git] / src / librustc / middle / trans / _match.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12  *
13  * # Compilation of match statements
14  *
15  * I will endeavor to explain the code as best I can.  I have only a loose
16  * understanding of some parts of it.
17  *
18  * ## Matching
19  *
20  * The basic state of the code is maintained in an array `m` of `Match`
21  * objects.  Each `Match` describes some list of patterns, all of which must
22  * match against the current list of values.  If those patterns match, then
23  * the arm listed in the match is the correct arm.  A given arm may have
24  * multiple corresponding match entries, one for each alternative that
25  * remains.  As we proceed these sets of matches are adjusted by the various
26  * `enter_XXX()` functions, each of which adjusts the set of options given
27  * some information about the value which has been matched.
28  *
29  * So, initially, there is one value and N matches, each of which have one
30  * constituent pattern.  N here is usually the number of arms but may be
31  * greater, if some arms have multiple alternatives.  For example, here:
32  *
33  *     enum Foo { A, B(int), C(uint, uint) }
34  *     match foo {
35  *         A => ...,
36  *         B(x) => ...,
37  *         C(1u, 2) => ...,
38  *         C(_) => ...
39  *     }
40  *
41  * The value would be `foo`.  There would be four matches, each of which
42  * contains one pattern (and, in one case, a guard).  We could collect the
43  * various options and then compile the code for the case where `foo` is an
44  * `A`, a `B`, and a `C`.  When we generate the code for `C`, we would (1)
45  * drop the two matches that do not match a `C` and (2) expand the other two
46  * into two patterns each.  In the first case, the two patterns would be `1u`
47  * and `2`, and the in the second case the _ pattern would be expanded into
48  * `_` and `_`.  The two values are of course the arguments to `C`.
49  *
50  * Here is a quick guide to the various functions:
51  *
52  * - `compile_submatch()`: The main workhouse.  It takes a list of values and
53  *   a list of matches and finds the various possibilities that could occur.
54  *
55  * - `enter_XXX()`: modifies the list of matches based on some information
56  *   about the value that has been matched.  For example,
57  *   `enter_rec_or_struct()` adjusts the values given that a record or struct
58  *   has been matched.  This is an infallible pattern, so *all* of the matches
59  *   must be either wildcards or record/struct patterns.  `enter_opt()`
60  *   handles the fallible cases, and it is correspondingly more complex.
61  *
62  * ## Bindings
63  *
64  * We store information about the bound variables for each arm as part of the
65  * per-arm `ArmData` struct.  There is a mapping from identifiers to
66  * `BindingInfo` structs.  These structs contain the mode/id/type of the
67  * binding, but they also contain up to two LLVM values, called `llmatch` and
68  * `llbinding` respectively (the `llbinding`, as will be described shortly, is
69  * optional and only present for by-value bindings---therefore it is bundled
70  * up as part of the `TransBindingMode` type).  Both point at allocas.
71  *
72  * The `llmatch` binding always stores a pointer into the value being matched
73  * which points at the data for the binding.  If the value being matched has
74  * type `T`, then, `llmatch` will point at an alloca of type `T*` (and hence
75  * `llmatch` has type `T**`).  So, if you have a pattern like:
76  *
77  *    let a: A = ...;
78  *    let b: B = ...;
79  *    match (a, b) { (ref c, d) => { ... } }
80  *
81  * For `c` and `d`, we would generate allocas of type `C*` and `D*`
82  * respectively.  These are called the `llmatch`.  As we match, when we come
83  * up against an identifier, we store the current pointer into the
84  * corresponding alloca.
85  *
86  * In addition, for each by-value binding (copy or move), we will create a
87  * second alloca (`llbinding`) that will hold the final value.  In this
88  * example, that means that `d` would have this second alloca of type `D` (and
89  * hence `llbinding` has type `D*`).
90  *
91  * Once a pattern is completely matched, and assuming that there is no guard
92  * pattern, we will branch to a block that leads to the body itself.  For any
93  * by-value bindings, this block will first load the ptr from `llmatch` (the
94  * one of type `D*`) and copy/move the value into `llbinding` (the one of type
95  * `D`).  The second alloca then becomes the value of the local variable.  For
96  * by ref bindings, the value of the local variable is simply the first
97  * alloca.
98  *
99  * So, for the example above, we would generate a setup kind of like this:
100  *
101  *        +-------+
102  *        | Entry |
103  *        +-------+
104  *            |
105  *        +-------------------------------------------+
106  *        | llmatch_c = (addr of first half of tuple) |
107  *        | llmatch_d = (addr of first half of tuple) |
108  *        +-------------------------------------------+
109  *            |
110  *        +--------------------------------------+
111  *        | *llbinding_d = **llmatch_dlbinding_d |
112  *        +--------------------------------------+
113  *
114  * If there is a guard, the situation is slightly different, because we must
115  * execute the guard code.  Moreover, we need to do so once for each of the
116  * alternatives that lead to the arm, because if the guard fails, they may
117  * have different points from which to continue the search. Therefore, in that
118  * case, we generate code that looks more like:
119  *
120  *        +-------+
121  *        | Entry |
122  *        +-------+
123  *            |
124  *        +-------------------------------------------+
125  *        | llmatch_c = (addr of first half of tuple) |
126  *        | llmatch_d = (addr of first half of tuple) |
127  *        +-------------------------------------------+
128  *            |
129  *        +-------------------------------------------------+
130  *        | *llbinding_d = **llmatch_dlbinding_d            |
131  *        | check condition                                 |
132  *        | if false { free *llbinding_d, goto next case }  |
133  *        | if true { goto body }                           |
134  *        +-------------------------------------------------+
135  *
136  * The handling for the cleanups is a bit... sensitive.  Basically, the body
137  * is the one that invokes `add_clean()` for each binding.  During the guard
138  * evaluation, we add temporary cleanups and revoke them after the guard is
139  * evaluated (it could fail, after all).  Presuming the guard fails, we drop
140  * the various values we copied explicitly.  Note that guards and moves are
141  * just plain incompatible.
142  *
143  * Some relevant helper functions that manage bindings:
144  * - `create_bindings_map()`
145  * - `store_non_ref_bindings()`
146  * - `insert_lllocals()`
147  *
148  *
149  * ## Notes on vector pattern matching.
150  *
151  * Vector pattern matching is surprisingly tricky. The problem is that
152  * the structure of the vector isn't fully known, and slice matches
153  * can be done on subparts of it.
154  *
155  * The way that vector pattern matches are dealt with, then, is as
156  * follows. First, we make the actual condition associated with a
157  * vector pattern simply a vector length comparison. So the pattern
158  * [1, .. x] gets the condition "vec len >= 1", and the pattern
159  * [.. x] gets the condition "vec len >= 0". The problem here is that
160  * having the condition "vec len >= 1" hold clearly does not mean that
161  * only a pattern that has exactly that condition will match. This
162  * means that it may well be the case that a condition holds, but none
163  * of the patterns matching that condition match; to deal with this,
164  * when doing vector length matches, we have match failures proceed to
165  * the next condition to check.
166  *
167  * There are a couple more subtleties to deal with. While the "actual"
168  * condition associated with vector length tests is simply a test on
169  * the vector length, the actual vec_len Opt entry contains more
170  * information used to restrict which matches are associated with it.
171  * So that all matches in a submatch are matching against the same
172  * values from inside the vector, they are split up by how many
173  * elements they match at the front and at the back of the vector. In
174  * order to make sure that arms are properly checked in order, even
175  * with the overmatching conditions, each vec_len Opt entry is
176  * associated with a range of matches.
177  * Consider the following:
178  *
179  *   match &[1, 2, 3] {
180  *       [1, 1, .. _] => 0,
181  *       [1, 2, 2, .. _] => 1,
182  *       [1, 2, 3, .. _] => 2,
183  *       [1, 2, .. _] => 3,
184  *       _ => 4
185  *   }
186  * The proper arm to match is arm 2, but arms 0 and 3 both have the
187  * condition "len >= 2". If arm 3 was lumped in with arm 0, then the
188  * wrong branch would be taken. Instead, vec_len Opts are associated
189  * with a contiguous range of matches that have the same "shape".
190  * This is sort of ugly and requires a bunch of special handling of
191  * vec_len options.
192  *
193  */
194
195 #[allow(non_camel_case_types)];
196
197 use back::abi;
198 use driver::session::FullDebugInfo;
199 use lib::llvm::{llvm, ValueRef, BasicBlockRef};
200 use middle::const_eval;
201 use middle::borrowck::root_map_key;
202 use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
203 use middle::pat_util::*;
204 use middle::resolve::DefMap;
205 use middle::trans::adt;
206 use middle::trans::base::*;
207 use middle::trans::build::*;
208 use middle::trans::callee;
209 use middle::trans::cleanup;
210 use middle::trans::cleanup::CleanupMethods;
211 use middle::trans::common::*;
212 use middle::trans::consts;
213 use middle::trans::controlflow;
214 use middle::trans::datum;
215 use middle::trans::datum::*;
216 use middle::trans::expr::Dest;
217 use middle::trans::expr;
218 use middle::trans::glue;
219 use middle::trans::tvec;
220 use middle::trans::type_of;
221 use middle::trans::debuginfo;
222 use middle::ty;
223 use util::common::indenter;
224 use util::ppaux::{Repr, vec_map_to_str};
225
226 use std::cell::Cell;
227 use collections::HashMap;
228 use std::vec;
229 use syntax::ast;
230 use syntax::ast::Ident;
231 use syntax::ast_util::path_to_ident;
232 use syntax::ast_util;
233 use syntax::codemap::{Span, DUMMY_SP};
234 use syntax::parse::token::InternedString;
235
236 // An option identifying a literal: either a unit-like struct or an
237 // expression.
238 enum Lit {
239     UnitLikeStructLit(ast::NodeId),    // the node ID of the pattern
240     ExprLit(@ast::Expr),
241     ConstLit(ast::DefId),              // the def ID of the constant
242 }
243
244 #[deriving(Eq)]
245 pub enum VecLenOpt {
246     vec_len_eq,
247     vec_len_ge(/* length of prefix */uint)
248 }
249
250 // An option identifying a branch (either a literal, an enum variant or a
251 // range)
252 enum Opt {
253     lit(Lit),
254     var(ty::Disr, @adt::Repr),
255     range(@ast::Expr, @ast::Expr),
256     vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
257 }
258
259 fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
260     match (a, b) {
261         (&lit(a), &lit(b)) => {
262             match (a, b) {
263                 (UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
264                 _ => {
265                     let a_expr;
266                     match a {
267                         ExprLit(existing_a_expr) => a_expr = existing_a_expr,
268                             ConstLit(a_const) => {
269                                 let e = const_eval::lookup_const_by_id(tcx, a_const);
270                                 a_expr = e.unwrap();
271                             }
272                         UnitLikeStructLit(_) => {
273                             fail!("UnitLikeStructLit should have been handled \
274                                     above")
275                         }
276                     }
277
278                     let b_expr;
279                     match b {
280                         ExprLit(existing_b_expr) => b_expr = existing_b_expr,
281                             ConstLit(b_const) => {
282                                 let e = const_eval::lookup_const_by_id(tcx, b_const);
283                                 b_expr = e.unwrap();
284                             }
285                         UnitLikeStructLit(_) => {
286                             fail!("UnitLikeStructLit should have been handled \
287                                     above")
288                         }
289                     }
290
291                     match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
292                         Some(val1) => val1 == 0,
293                         None => fail!("compare_list_exprs: type mismatch"),
294                     }
295                 }
296             }
297         }
298         (&range(a1, a2), &range(b1, b2)) => {
299             let m1 = const_eval::compare_lit_exprs(tcx, a1, b1);
300             let m2 = const_eval::compare_lit_exprs(tcx, a2, b2);
301             match (m1, m2) {
302                 (Some(val1), Some(val2)) => (val1 == 0 && val2 == 0),
303                 _ => fail!("compare_list_exprs: type mismatch"),
304             }
305         }
306         (&var(a, _), &var(b, _)) => a == b,
307         (&vec_len(a1, a2, _), &vec_len(b1, b2, _)) =>
308             a1 == b1 && a2 == b2,
309         _ => false
310     }
311 }
312
313 pub enum opt_result<'a> {
314     single_result(Result<'a>),
315     lower_bound(Result<'a>),
316     range_result(Result<'a>, Result<'a>),
317 }
318
319 fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
320     let _icx = push_ctxt("match::trans_opt");
321     let ccx = bcx.ccx();
322     let mut bcx = bcx;
323     match *o {
324         lit(ExprLit(lit_expr)) => {
325             let lit_datum = unpack_datum!(bcx, expr::trans(bcx, lit_expr));
326             let lit_datum = lit_datum.assert_rvalue(bcx); // literals are rvalues
327             let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
328             return single_result(rslt(bcx, lit_datum.val));
329         }
330         lit(UnitLikeStructLit(pat_id)) => {
331             let struct_ty = ty::node_id_to_type(bcx.tcx(), pat_id);
332             let datum = datum::rvalue_scratch_datum(bcx, struct_ty, "");
333             return single_result(rslt(bcx, datum.val));
334         }
335         lit(ConstLit(lit_id)) => {
336             let (llval, _) = consts::get_const_val(bcx.ccx(), lit_id);
337             return single_result(rslt(bcx, llval));
338         }
339         var(disr_val, repr) => {
340             return adt::trans_case(bcx, repr, disr_val);
341         }
342         range(l1, l2) => {
343             let (l1, _) = consts::const_expr(ccx, l1, true);
344             let (l2, _) = consts::const_expr(ccx, l2, true);
345             return range_result(rslt(bcx, l1), rslt(bcx, l2));
346         }
347         vec_len(n, vec_len_eq, _) => {
348             return single_result(rslt(bcx, C_int(ccx, n as int)));
349         }
350         vec_len(n, vec_len_ge(_), _) => {
351             return lower_bound(rslt(bcx, C_int(ccx, n as int)));
352         }
353     }
354 }
355
356 fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
357     let ccx = bcx.ccx();
358     let def_map = ccx.tcx.def_map.borrow();
359     match def_map.get().get_copy(&pat_id) {
360         ast::DefVariant(enum_id, var_id, _) => {
361             let variants = ty::enum_variants(ccx.tcx, enum_id);
362             for v in (*variants).iter() {
363                 if var_id == v.id {
364                     return var(v.disr_val,
365                                adt::represent_node(bcx, pat_id))
366                 }
367             }
368             unreachable!();
369         }
370         ast::DefFn(..) |
371         ast::DefStruct(_) => {
372             return lit(UnitLikeStructLit(pat_id));
373         }
374         _ => {
375             ccx.sess.bug("non-variant or struct in variant_opt()");
376         }
377     }
378 }
379
380 #[deriving(Clone)]
381 enum TransBindingMode {
382     TrByValue(/*llbinding:*/ ValueRef),
383     TrByRef,
384 }
385
386 /**
387  * Information about a pattern binding:
388  * - `llmatch` is a pointer to a stack slot.  The stack slot contains a
389  *   pointer into the value being matched.  Hence, llmatch has type `T**`
390  *   where `T` is the value being matched.
391  * - `trmode` is the trans binding mode
392  * - `id` is the node id of the binding
393  * - `ty` is the Rust type of the binding */
394  #[deriving(Clone)]
395 struct BindingInfo {
396     llmatch: ValueRef,
397     trmode: TransBindingMode,
398     id: ast::NodeId,
399     span: Span,
400     ty: ty::t,
401 }
402
403 type BindingsMap = HashMap<Ident, BindingInfo>;
404
405 struct ArmData<'a,'b> {
406     bodycx: &'b Block<'b>,
407     arm: &'a ast::Arm,
408     bindings_map: @BindingsMap
409 }
410
411 // FIXME #11820: method resolution is unreliable with &
412 impl<'a,'b> Clone for ArmData<'a, 'b> {
413     fn clone(&self) -> ArmData<'a, 'b> { *self }
414 }
415
416 /**
417  * Info about Match.
418  * If all `pats` are matched then arm `data` will be executed.
419  * As we proceed `bound_ptrs` are filled with pointers to values to be bound,
420  * these pointers are stored in llmatch variables just before executing `data` arm.
421  */
422 #[deriving(Clone)]
423 struct Match<'a,'b> {
424     pats: ~[@ast::Pat],
425     data: ArmData<'a,'b>,
426     bound_ptrs: ~[(Ident, ValueRef)]
427 }
428
429 impl<'a,'b> Repr for Match<'a,'b> {
430     fn repr(&self, tcx: ty::ctxt) -> ~str {
431         if tcx.sess.verbose() {
432             // for many programs, this just take too long to serialize
433             self.pats.repr(tcx)
434         } else {
435             format!("{} pats", self.pats.len())
436         }
437     }
438 }
439
440 fn has_nested_bindings(m: &[Match], col: uint) -> bool {
441     for br in m.iter() {
442         match br.pats[col].node {
443           ast::PatIdent(_, _, Some(_)) => return true,
444           _ => ()
445         }
446     }
447     return false;
448 }
449
450 fn expand_nested_bindings<'r,'b>(
451                           bcx: &'b Block<'b>,
452                           m: &[Match<'r,'b>],
453                           col: uint,
454                           val: ValueRef)
455                           -> ~[Match<'r,'b>] {
456     debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})",
457            bcx.to_str(),
458            m.repr(bcx.tcx()),
459            col,
460            bcx.val_to_str(val));
461     let _indenter = indenter();
462
463     m.map(|br| {
464         match br.pats[col].node {
465             ast::PatIdent(_, ref path, Some(inner)) => {
466                 let pats = vec::append(
467                     br.pats.slice(0u, col).to_owned(),
468                     vec::append(~[inner],
469                                 br.pats.slice(col + 1u,
470                                            br.pats.len())));
471
472                 let mut res = Match {
473                     pats: pats,
474                     data: br.data.clone(),
475                     bound_ptrs: br.bound_ptrs.clone()
476                 };
477                 res.bound_ptrs.push((path_to_ident(path), val));
478                 res
479             }
480             _ => (*br).clone(),
481         }
482     })
483 }
484
485 fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
486     if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
487         bcx.sess().span_bug(
488             p.span,
489             format!("expected an identifier pattern but found p: {}",
490                  p.repr(bcx.tcx())));
491     }
492 }
493
494 type enter_pat<'a> = 'a |@ast::Pat| -> Option<~[@ast::Pat]>;
495
496 fn enter_match<'r,'b>(
497                bcx: &'b Block<'b>,
498                dm: DefMap,
499                m: &[Match<'r,'b>],
500                col: uint,
501                val: ValueRef,
502                e: enter_pat)
503                -> ~[Match<'r,'b>] {
504     debug!("enter_match(bcx={}, m={}, col={}, val={})",
505            bcx.to_str(),
506            m.repr(bcx.tcx()),
507            col,
508            bcx.val_to_str(val));
509     let _indenter = indenter();
510
511     let mut result = ~[];
512     for br in m.iter() {
513         match e(br.pats[col]) {
514             Some(sub) => {
515                 let pats =
516                     vec::append(
517                         vec::append(sub, br.pats.slice(0u, col)),
518                         br.pats.slice(col + 1u, br.pats.len()));
519
520                 let this = br.pats[col];
521                 let mut bound_ptrs = br.bound_ptrs.clone();
522                 match this.node {
523                     ast::PatIdent(_, ref path, None) => {
524                         if pat_is_binding(dm, this) {
525                             bound_ptrs.push((path_to_ident(path), val));
526                         }
527                     }
528                     _ => {}
529                 }
530
531                 result.push(Match {
532                     pats: pats,
533                     data: br.data.clone(),
534                     bound_ptrs: bound_ptrs
535                 });
536             }
537             None => ()
538         }
539     }
540
541     debug!("result={}", result.repr(bcx.tcx()));
542
543     return result;
544 }
545
546 fn enter_default<'r,'b>(
547                  bcx: &'b Block<'b>,
548                  dm: DefMap,
549                  m: &[Match<'r,'b>],
550                  col: uint,
551                  val: ValueRef,
552                  chk: &FailureHandler)
553                  -> ~[Match<'r,'b>] {
554     debug!("enter_default(bcx={}, m={}, col={}, val={})",
555            bcx.to_str(),
556            m.repr(bcx.tcx()),
557            col,
558            bcx.val_to_str(val));
559     let _indenter = indenter();
560
561     // Collect all of the matches that can match against anything.
562     let matches = enter_match(bcx, dm, m, col, val, |p| {
563         match p.node {
564           ast::PatWild | ast::PatWildMulti | ast::PatTup(_) => Some(~[]),
565           ast::PatIdent(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
566           _ => None
567         }
568     });
569
570     // Ok, now, this is pretty subtle. A "default" match is a match
571     // that needs to be considered if none of the actual checks on the
572     // value being considered succeed. The subtlety lies in that sometimes
573     // identifier/wildcard matches are *not* default matches. Consider:
574     // "match x { _ if something => foo, true => bar, false => baz }".
575     // There is a wildcard match, but it is *not* a default case. The boolean
576     // case on the value being considered is exhaustive. If the case is
577     // exhaustive, then there are no defaults.
578     //
579     // We detect whether the case is exhaustive in the following
580     // somewhat kludgy way: if the last wildcard/binding match has a
581     // guard, then by non-redundancy, we know that there aren't any
582     // non guarded matches, and thus by exhaustiveness, we know that
583     // we don't need any default cases. If the check *isn't* nonexhaustive
584     // (because chk is Some), then we need the defaults anyways.
585     let is_exhaustive = match matches.last() {
586         Some(m) if m.data.arm.guard.is_some() && chk.is_infallible() => true,
587         _ => false
588     };
589
590     if is_exhaustive { ~[] } else { matches }
591 }
592
593 // <pcwalton> nmatsakis: what does enter_opt do?
594 // <pcwalton> in trans/match
595 // <pcwalton> trans/match.rs is like stumbling around in a dark cave
596 // <nmatsakis> pcwalton: the enter family of functions adjust the set of
597 //             patterns as needed
598 // <nmatsakis> yeah, at some point I kind of achieved some level of
599 //             understanding
600 // <nmatsakis> anyhow, they adjust the patterns given that something of that
601 //             kind has been found
602 // <nmatsakis> pcwalton: ok, right, so enter_XXX() adjusts the patterns, as I
603 //             said
604 // <nmatsakis> enter_match() kind of embodies the generic code
605 // <nmatsakis> it is provided with a function that tests each pattern to see
606 //             if it might possibly apply and so forth
607 // <nmatsakis> so, if you have a pattern like {a: _, b: _, _} and one like _
608 // <nmatsakis> then _ would be expanded to (_, _)
609 // <nmatsakis> one spot for each of the sub-patterns
610 // <nmatsakis> enter_opt() is one of the more complex; it covers the fallible
611 //             cases
612 // <nmatsakis> enter_rec_or_struct() or enter_tuple() are simpler, since they
613 //             are infallible patterns
614 // <nmatsakis> so all patterns must either be records (resp. tuples) or
615 //             wildcards
616
617 fn enter_opt<'r,'b>(
618              bcx: &'b Block<'b>,
619              m: &[Match<'r,'b>],
620              opt: &Opt,
621              col: uint,
622              variant_size: uint,
623              val: ValueRef)
624              -> ~[Match<'r,'b>] {
625     debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})",
626            bcx.to_str(),
627            m.repr(bcx.tcx()),
628            *opt,
629            col,
630            bcx.val_to_str(val));
631     let _indenter = indenter();
632
633     let tcx = bcx.tcx();
634     let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
635     let mut i = 0;
636     enter_match(bcx, tcx.def_map, m, col, val, |p| {
637         let answer = match p.node {
638             ast::PatEnum(..) |
639             ast::PatIdent(_, _, None) if pat_is_const(tcx.def_map, p) => {
640                 let const_def = {
641                     let def_map = tcx.def_map.borrow();
642                     def_map.get().get_copy(&p.id)
643                 };
644                 let const_def_id = ast_util::def_id_of_def(const_def);
645                 if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
646                     Some(~[])
647                 } else {
648                     None
649                 }
650             }
651             ast::PatEnum(_, ref subpats) => {
652                 if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
653                     // FIXME: Must we clone?
654                     match *subpats {
655                         None => Some(vec::from_elem(variant_size, dummy)),
656                         Some(ref subpats) => {
657                             Some((*subpats).iter().map(|x| *x).collect())
658                         }
659                     }
660                 } else {
661                     None
662                 }
663             }
664             ast::PatIdent(_, _, None)
665                     if pat_is_variant_or_struct(tcx.def_map, p) => {
666                 if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
667                     Some(~[])
668                 } else {
669                     None
670                 }
671             }
672             ast::PatLit(l) => {
673                 if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(~[])} else {None}
674             }
675             ast::PatRange(l1, l2) => {
676                 if opt_eq(tcx, &range(l1, l2), opt) {Some(~[])} else {None}
677             }
678             ast::PatStruct(_, ref field_pats, _) => {
679                 if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
680                     // Look up the struct variant ID.
681                     let struct_id;
682                     let defn = {
683                         let def_map = tcx.def_map.borrow();
684                         def_map.get().get_copy(&p.id)
685                     };
686                     match defn {
687                         ast::DefVariant(_, found_struct_id, _) => {
688                             struct_id = found_struct_id;
689                         }
690                         _ => {
691                             tcx.sess.span_bug(p.span, "expected enum variant def");
692                         }
693                     }
694
695                     // Reorder the patterns into the same order they were
696                     // specified in the struct definition. Also fill in
697                     // unspecified fields with dummy.
698                     let mut reordered_patterns = ~[];
699                     let r = ty::lookup_struct_fields(tcx, struct_id);
700                     for field in r.iter() {
701                             match field_pats.iter().find(|p| p.ident.name
702                                                          == field.name) {
703                                 None => reordered_patterns.push(dummy),
704                                 Some(fp) => reordered_patterns.push(fp.pat)
705                             }
706                     }
707                     Some(reordered_patterns)
708                 } else {
709                     None
710                 }
711             }
712             ast::PatVec(ref before, slice, ref after) => {
713                 let (lo, hi) = match *opt {
714                     vec_len(_, _, (lo, hi)) => (lo, hi),
715                     _ => tcx.sess.span_bug(p.span,
716                                            "vec pattern but not vec opt")
717                 };
718
719                 match slice {
720                     Some(slice) if i >= lo && i <= hi => {
721                         let n = before.len() + after.len();
722                         let this_opt = vec_len(n, vec_len_ge(before.len()),
723                                                (lo, hi));
724                         if opt_eq(tcx, &this_opt, opt) {
725                             let mut new_before = ~[];
726                             for pat in before.iter() {
727                                 new_before.push(*pat);
728                             }
729                             new_before.push(slice);
730                             for pat in after.iter() {
731                                 new_before.push(*pat);
732                             }
733                             Some(new_before)
734                         } else {
735                             None
736                         }
737                     }
738                     None if i >= lo && i <= hi => {
739                         let n = before.len();
740                         if opt_eq(tcx, &vec_len(n, vec_len_eq, (lo,hi)), opt) {
741                             let mut new_before = ~[];
742                             for pat in before.iter() {
743                                 new_before.push(*pat);
744                             }
745                             Some(new_before)
746                         } else {
747                             None
748                         }
749                     }
750                     _ => None
751                 }
752             }
753             _ => {
754                 assert_is_binding_or_wild(bcx, p);
755                 // In most cases, a binding/wildcard match be
756                 // considered to match against any Opt. However, when
757                 // doing vector pattern matching, submatches are
758                 // considered even if the eventual match might be from
759                 // a different submatch. Thus, when a submatch fails
760                 // when doing a vector match, we proceed to the next
761                 // submatch. Thus, including a default match would
762                 // cause the default match to fire spuriously.
763                 match *opt {
764                     vec_len(..) => None,
765                     _ => Some(vec::from_elem(variant_size, dummy))
766                 }
767             }
768         };
769         i += 1;
770         answer
771     })
772 }
773
774 fn enter_rec_or_struct<'r,'b>(
775                        bcx: &'b Block<'b>,
776                        dm: DefMap,
777                        m: &[Match<'r,'b>],
778                        col: uint,
779                        fields: &[ast::Ident],
780                        val: ValueRef)
781                        -> ~[Match<'r,'b>] {
782     debug!("enter_rec_or_struct(bcx={}, m={}, col={}, val={})",
783            bcx.to_str(),
784            m.repr(bcx.tcx()),
785            col,
786            bcx.val_to_str(val));
787     let _indenter = indenter();
788
789     let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
790     enter_match(bcx, dm, m, col, val, |p| {
791         match p.node {
792             ast::PatStruct(_, ref fpats, _) => {
793                 let mut pats = ~[];
794                 for fname in fields.iter() {
795                     match fpats.iter().find(|p| p.ident.name == fname.name) {
796                         None => pats.push(dummy),
797                         Some(pat) => pats.push(pat.pat)
798                     }
799                 }
800                 Some(pats)
801             }
802             _ => {
803                 assert_is_binding_or_wild(bcx, p);
804                 Some(vec::from_elem(fields.len(), dummy))
805             }
806         }
807     })
808 }
809
810 fn enter_tup<'r,'b>(
811              bcx: &'b Block<'b>,
812              dm: DefMap,
813              m: &[Match<'r,'b>],
814              col: uint,
815              val: ValueRef,
816              n_elts: uint)
817              -> ~[Match<'r,'b>] {
818     debug!("enter_tup(bcx={}, m={}, col={}, val={})",
819            bcx.to_str(),
820            m.repr(bcx.tcx()),
821            col,
822            bcx.val_to_str(val));
823     let _indenter = indenter();
824
825     let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
826     enter_match(bcx, dm, m, col, val, |p| {
827         match p.node {
828             ast::PatTup(ref elts) => {
829                 let mut new_elts = ~[];
830                 for elt in elts.iter() {
831                     new_elts.push((*elt).clone())
832                 }
833                 Some(new_elts)
834             }
835             _ => {
836                 assert_is_binding_or_wild(bcx, p);
837                 Some(vec::from_elem(n_elts, dummy))
838             }
839         }
840     })
841 }
842
843 fn enter_tuple_struct<'r,'b>(
844                       bcx: &'b Block<'b>,
845                       dm: DefMap,
846                       m: &[Match<'r,'b>],
847                       col: uint,
848                       val: ValueRef,
849                       n_elts: uint)
850                       -> ~[Match<'r,'b>] {
851     debug!("enter_tuple_struct(bcx={}, m={}, col={}, val={})",
852            bcx.to_str(),
853            m.repr(bcx.tcx()),
854            col,
855            bcx.val_to_str(val));
856     let _indenter = indenter();
857
858     let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
859     enter_match(bcx, dm, m, col, val, |p| {
860         match p.node {
861             ast::PatEnum(_, Some(ref elts)) => {
862                 Some(elts.iter().map(|x| (*x)).collect())
863             }
864             _ => {
865                 assert_is_binding_or_wild(bcx, p);
866                 Some(vec::from_elem(n_elts, dummy))
867             }
868         }
869     })
870 }
871
872 fn enter_uniq<'r,'b>(
873               bcx: &'b Block<'b>,
874               dm: DefMap,
875               m: &[Match<'r,'b>],
876               col: uint,
877               val: ValueRef)
878               -> ~[Match<'r,'b>] {
879     debug!("enter_uniq(bcx={}, m={}, col={}, val={})",
880            bcx.to_str(),
881            m.repr(bcx.tcx()),
882            col,
883            bcx.val_to_str(val));
884     let _indenter = indenter();
885
886     let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
887     enter_match(bcx, dm, m, col, val, |p| {
888         match p.node {
889             ast::PatUniq(sub) => {
890                 Some(~[sub])
891             }
892             _ => {
893                 assert_is_binding_or_wild(bcx, p);
894                 Some(~[dummy])
895             }
896         }
897     })
898 }
899
900 fn enter_region<'r,
901                 'b>(
902                 bcx: &'b Block<'b>,
903                 dm: DefMap,
904                 m: &[Match<'r,'b>],
905                 col: uint,
906                 val: ValueRef)
907                 -> ~[Match<'r,'b>] {
908     debug!("enter_region(bcx={}, m={}, col={}, val={})",
909            bcx.to_str(),
910            m.repr(bcx.tcx()),
911            col,
912            bcx.val_to_str(val));
913     let _indenter = indenter();
914
915     let dummy = @ast::Pat { id: 0, node: ast::PatWild, span: DUMMY_SP };
916     enter_match(bcx, dm, m, col, val, |p| {
917         match p.node {
918             ast::PatRegion(sub) => {
919                 Some(~[sub])
920             }
921             _ => {
922                 assert_is_binding_or_wild(bcx, p);
923                 Some(~[dummy])
924             }
925         }
926     })
927 }
928
929 // Returns the options in one column of matches. An option is something that
930 // needs to be conditionally matched at runtime; for example, the discriminant
931 // on a set of enum variants or a literal.
932 fn get_options(bcx: &Block, m: &[Match], col: uint) -> ~[Opt] {
933     let ccx = bcx.ccx();
934     fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
935         if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
936         set.push(val);
937     }
938     // Vector comparisions are special in that since the actual
939     // conditions over-match, we need to be careful about them. This
940     // means that in order to properly handle things in order, we need
941     // to not always merge conditions.
942     fn add_veclen_to_set(set: &mut ~[Opt], i: uint,
943                          len: uint, vlo: VecLenOpt) {
944         match set.last() {
945             // If the last condition in the list matches the one we want
946             // to add, then extend its range. Otherwise, make a new
947             // vec_len with a range just covering the new entry.
948             Some(&vec_len(len2, vlo2, (start, end)))
949                  if len == len2 && vlo == vlo2 =>
950                  set[set.len() - 1] = vec_len(len, vlo, (start, end+1)),
951             _ => set.push(vec_len(len, vlo, (i, i)))
952         }
953     }
954
955     let mut found = ~[];
956     for (i, br) in m.iter().enumerate() {
957         let cur = br.pats[col];
958         match cur.node {
959             ast::PatLit(l) => {
960                 add_to_set(ccx.tcx, &mut found, lit(ExprLit(l)));
961             }
962             ast::PatIdent(..) => {
963                 // This is one of: an enum variant, a unit-like struct, or a
964                 // variable binding.
965                 let opt_def = {
966                     let def_map = ccx.tcx.def_map.borrow();
967                     def_map.get().find_copy(&cur.id)
968                 };
969                 match opt_def {
970                     Some(ast::DefVariant(..)) => {
971                         add_to_set(ccx.tcx, &mut found,
972                                    variant_opt(bcx, cur.id));
973                     }
974                     Some(ast::DefStruct(..)) => {
975                         add_to_set(ccx.tcx, &mut found,
976                                    lit(UnitLikeStructLit(cur.id)));
977                     }
978                     Some(ast::DefStatic(const_did, false)) => {
979                         add_to_set(ccx.tcx, &mut found,
980                                    lit(ConstLit(const_did)));
981                     }
982                     _ => {}
983                 }
984             }
985             ast::PatEnum(..) | ast::PatStruct(..) => {
986                 // This could be one of: a tuple-like enum variant, a
987                 // struct-like enum variant, or a struct.
988                 let opt_def = {
989                     let def_map = ccx.tcx.def_map.borrow();
990                     def_map.get().find_copy(&cur.id)
991                 };
992                 match opt_def {
993                     Some(ast::DefFn(..)) |
994                     Some(ast::DefVariant(..)) => {
995                         add_to_set(ccx.tcx, &mut found,
996                                    variant_opt(bcx, cur.id));
997                     }
998                     Some(ast::DefStatic(const_did, false)) => {
999                         add_to_set(ccx.tcx, &mut found,
1000                                    lit(ConstLit(const_did)));
1001                     }
1002                     _ => {}
1003                 }
1004             }
1005             ast::PatRange(l1, l2) => {
1006                 add_to_set(ccx.tcx, &mut found, range(l1, l2));
1007             }
1008             ast::PatVec(ref before, slice, ref after) => {
1009                 let (len, vec_opt) = match slice {
1010                     None => (before.len(), vec_len_eq),
1011                     Some(_) => (before.len() + after.len(),
1012                                 vec_len_ge(before.len()))
1013                 };
1014                 add_veclen_to_set(&mut found, i, len, vec_opt);
1015             }
1016             _ => {}
1017         }
1018     }
1019     return found;
1020 }
1021
1022 struct ExtractedBlock<'a> {
1023     vals: ~[ValueRef],
1024     bcx: &'a Block<'a>,
1025 }
1026
1027 fn extract_variant_args<'a>(
1028                         bcx: &'a Block<'a>,
1029                         repr: &adt::Repr,
1030                         disr_val: ty::Disr,
1031                         val: ValueRef)
1032                         -> ExtractedBlock<'a> {
1033     let _icx = push_ctxt("match::extract_variant_args");
1034     let args = vec::from_fn(adt::num_args(repr, disr_val), |i| {
1035         adt::trans_field_ptr(bcx, repr, val, disr_val, i)
1036     });
1037
1038     ExtractedBlock { vals: args, bcx: bcx }
1039 }
1040
1041 fn match_datum(bcx: &Block,
1042                val: ValueRef,
1043                pat_id: ast::NodeId)
1044                -> Datum<Lvalue> {
1045     /*!
1046      * Helper for converting from the ValueRef that we pass around in
1047      * the match code, which is always an lvalue, into a Datum. Eventually
1048      * we should just pass around a Datum and be done with it.
1049      */
1050
1051     let ty = node_id_type(bcx, pat_id);
1052     Datum(val, ty, Lvalue)
1053 }
1054
1055
1056 fn extract_vec_elems<'a>(
1057                      bcx: &'a Block<'a>,
1058                      pat_id: ast::NodeId,
1059                      elem_count: uint,
1060                      slice: Option<uint>,
1061                      val: ValueRef,
1062                      count: ValueRef)
1063                      -> ExtractedBlock<'a> {
1064     let _icx = push_ctxt("match::extract_vec_elems");
1065     let vec_datum = match_datum(bcx, val, pat_id);
1066     let (base, len) = vec_datum.get_vec_base_and_len(bcx);
1067     let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
1068
1069     let mut elems = vec::from_fn(elem_count, |i| {
1070         match slice {
1071             None => GEPi(bcx, base, [i]),
1072             Some(n) if i < n => GEPi(bcx, base, [i]),
1073             Some(n) if i > n => {
1074                 InBoundsGEP(bcx, base, [
1075                     Sub(bcx, count,
1076                         C_int(bcx.ccx(), (elem_count - i) as int))])
1077             }
1078             _ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty.to_ref()) }
1079         }
1080     });
1081     if slice.is_some() {
1082         let n = slice.unwrap();
1083         let slice_byte_offset = Mul(bcx, vt.llunit_size, C_uint(bcx.ccx(), n));
1084         let slice_begin = tvec::pointer_add_byte(bcx, base, slice_byte_offset);
1085         let slice_len_offset = C_uint(bcx.ccx(), elem_count - 1u);
1086         let slice_len = Sub(bcx, len, slice_len_offset);
1087         let slice_ty = ty::mk_vec(bcx.tcx(),
1088             ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable},
1089             ty::vstore_slice(ty::ReStatic)
1090         );
1091         let scratch = rvalue_scratch_datum(bcx, slice_ty, "");
1092         Store(bcx, slice_begin,
1093               GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
1094         Store(bcx, slice_len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
1095         elems[n] = scratch.val;
1096     }
1097
1098     ExtractedBlock { vals: elems, bcx: bcx }
1099 }
1100
1101 /// Checks every pattern in `m` at `col` column.
1102 /// If there are a struct pattern among them function
1103 /// returns list of all fields that are matched in these patterns.
1104 /// Function returns None if there is no struct pattern.
1105 /// Function doesn't collect fields from struct-like enum variants.
1106 /// Function can return empty list if there is only wildcard struct pattern.
1107 fn collect_record_or_struct_fields<'a>(
1108                                    bcx: &'a Block<'a>,
1109                                    m: &[Match],
1110                                    col: uint)
1111                                    -> Option<~[ast::Ident]> {
1112     let mut fields: ~[ast::Ident] = ~[];
1113     let mut found = false;
1114     for br in m.iter() {
1115         match br.pats[col].node {
1116           ast::PatStruct(_, ref fs, _) => {
1117             match ty::get(node_id_type(bcx, br.pats[col].id)).sty {
1118               ty::ty_struct(..) => {
1119                    extend(&mut fields, fs.as_slice());
1120                    found = true;
1121               }
1122               _ => ()
1123             }
1124           }
1125           _ => ()
1126         }
1127     }
1128     if found {
1129         return Some(fields);
1130     } else {
1131         return None;
1132     }
1133
1134     fn extend(idents: &mut ~[ast::Ident], field_pats: &[ast::FieldPat]) {
1135         for field_pat in field_pats.iter() {
1136             let field_ident = field_pat.ident;
1137             if !idents.iter().any(|x| x.name == field_ident.name) {
1138                 idents.push(field_ident);
1139             }
1140         }
1141     }
1142 }
1143
1144 fn pats_require_rooting(bcx: &Block, m: &[Match], col: uint) -> bool {
1145     m.iter().any(|br| {
1146         let pat_id = br.pats[col].id;
1147         let key = root_map_key {id: pat_id, derefs: 0u };
1148         let root_map = bcx.ccx().maps.root_map.borrow();
1149         root_map.get().contains_key(&key)
1150     })
1151 }
1152
1153 // Macro for deciding whether any of the remaining matches fit a given kind of
1154 // pattern.  Note that, because the macro is well-typed, either ALL of the
1155 // matches should fit that sort of pattern or NONE (however, some of the
1156 // matches may be wildcards like _ or identifiers).
1157 macro_rules! any_pat (
1158     ($m:expr, $pattern:pat) => (
1159         ($m).iter().any(|br| {
1160             match br.pats[col].node {
1161                 $pattern => true,
1162                 _ => false
1163             }
1164         })
1165     )
1166 )
1167
1168 fn any_uniq_pat(m: &[Match], col: uint) -> bool {
1169     any_pat!(m, ast::PatUniq(_))
1170 }
1171
1172 fn any_region_pat(m: &[Match], col: uint) -> bool {
1173     any_pat!(m, ast::PatRegion(_))
1174 }
1175
1176 fn any_tup_pat(m: &[Match], col: uint) -> bool {
1177     any_pat!(m, ast::PatTup(_))
1178 }
1179
1180 fn any_tuple_struct_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
1181     m.iter().any(|br| {
1182         let pat = br.pats[col];
1183         match pat.node {
1184             ast::PatEnum(_, Some(_)) => {
1185                 let def_map = bcx.tcx().def_map.borrow();
1186                 match def_map.get().find(&pat.id) {
1187                     Some(&ast::DefFn(..)) |
1188                     Some(&ast::DefStruct(..)) => true,
1189                     _ => false
1190                 }
1191             }
1192             _ => false
1193         }
1194     })
1195 }
1196
1197 struct DynamicFailureHandler<'a> {
1198     bcx: &'a Block<'a>,
1199     sp: Span,
1200     msg: InternedString,
1201     finished: @Cell<Option<BasicBlockRef>>,
1202 }
1203
1204 impl<'a> DynamicFailureHandler<'a> {
1205     fn handle_fail(&self) -> BasicBlockRef {
1206         match self.finished.get() {
1207             Some(bb) => return bb,
1208             _ => (),
1209         }
1210
1211         let fcx = self.bcx.fcx;
1212         let fail_cx = fcx.new_block(false, "case_fallthrough", None);
1213         controlflow::trans_fail(fail_cx, self.sp, self.msg.clone());
1214         self.finished.set(Some(fail_cx.llbb));
1215         fail_cx.llbb
1216     }
1217 }
1218
1219 /// What to do when the pattern match fails.
1220 enum FailureHandler<'a> {
1221     Infallible,
1222     JumpToBasicBlock(BasicBlockRef),
1223     DynamicFailureHandlerClass(~DynamicFailureHandler<'a>),
1224 }
1225
1226 impl<'a> FailureHandler<'a> {
1227     fn is_infallible(&self) -> bool {
1228         match *self {
1229             Infallible => true,
1230             _ => false,
1231         }
1232     }
1233
1234     fn is_fallible(&self) -> bool {
1235         !self.is_infallible()
1236     }
1237
1238     fn handle_fail(&self) -> BasicBlockRef {
1239         match *self {
1240             Infallible => {
1241                 fail!("attempted to fail in infallible failure handler!")
1242             }
1243             JumpToBasicBlock(basic_block) => basic_block,
1244             DynamicFailureHandlerClass(ref dynamic_failure_handler) => {
1245                 dynamic_failure_handler.handle_fail()
1246             }
1247         }
1248     }
1249 }
1250
1251 fn pick_col(m: &[Match]) -> uint {
1252     fn score(p: &ast::Pat) -> uint {
1253         match p.node {
1254           ast::PatLit(_) | ast::PatEnum(_, _) | ast::PatRange(_, _) => 1u,
1255           ast::PatIdent(_, _, Some(p)) => score(p),
1256           _ => 0u
1257         }
1258     }
1259     let mut scores = vec::from_elem(m[0].pats.len(), 0u);
1260     for br in m.iter() {
1261         for (i, p) in br.pats.iter().enumerate() {
1262             scores[i] += score(*p);
1263         }
1264     }
1265     let mut max_score = 0u;
1266     let mut best_col = 0u;
1267     for (i, score) in scores.iter().enumerate() {
1268         let score = *score;
1269
1270         // Irrefutable columns always go first, they'd only be duplicated in
1271         // the branches.
1272         if score == 0u { return i; }
1273         // If no irrefutable ones are found, we pick the one with the biggest
1274         // branching factor.
1275         if score > max_score { max_score = score; best_col = i; }
1276     }
1277     return best_col;
1278 }
1279
1280 #[deriving(Eq)]
1281 pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
1282
1283 // Compiles a comparison between two things.
1284 //
1285 // NB: This must produce an i1, not a Rust bool (i8).
1286 fn compare_values<'a>(
1287                   cx: &'a Block<'a>,
1288                   lhs: ValueRef,
1289                   rhs: ValueRef,
1290                   rhs_t: ty::t)
1291                   -> Result<'a> {
1292     let _icx = push_ctxt("compare_values");
1293     if ty::type_is_scalar(rhs_t) {
1294       let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq);
1295       return rslt(rs.bcx, rs.val);
1296     }
1297
1298     match ty::get(rhs_t).sty {
1299         ty::ty_str(ty::vstore_uniq) => {
1300             let scratch_lhs = alloca(cx, val_ty(lhs), "__lhs");
1301             Store(cx, lhs, scratch_lhs);
1302             let scratch_rhs = alloca(cx, val_ty(rhs), "__rhs");
1303             Store(cx, rhs, scratch_rhs);
1304             let did = langcall(cx, None,
1305                                format!("comparison of `{}`", cx.ty_to_str(rhs_t)),
1306                                UniqStrEqFnLangItem);
1307             let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None);
1308             Result {
1309                 bcx: result.bcx,
1310                 val: bool_to_i1(result.bcx, result.val)
1311             }
1312         }
1313         ty::ty_str(_) => {
1314             let did = langcall(cx, None,
1315                                format!("comparison of `{}`", cx.ty_to_str(rhs_t)),
1316                                StrEqFnLangItem);
1317             let result = callee::trans_lang_call(cx, did, [lhs, rhs], None);
1318             Result {
1319                 bcx: result.bcx,
1320                 val: bool_to_i1(result.bcx, result.val)
1321             }
1322         }
1323         _ => {
1324             cx.tcx().sess.bug("only scalars and strings supported in \
1325                                 compare_values");
1326         }
1327     }
1328 }
1329
1330 fn store_non_ref_bindings<'a>(
1331                           bcx: &'a Block<'a>,
1332                           bindings_map: &BindingsMap,
1333                           opt_cleanup_scope: Option<cleanup::ScopeId>)
1334                           -> &'a Block<'a>
1335 {
1336     /*!
1337      * For each copy/move binding, copy the value from the value being
1338      * matched into its final home.  This code executes once one of
1339      * the patterns for a given arm has completely matched.  It adds
1340      * cleanups to the `opt_cleanup_scope`, if one is provided.
1341      */
1342
1343     let fcx = bcx.fcx;
1344     let mut bcx = bcx;
1345     for (_, &binding_info) in bindings_map.iter() {
1346         match binding_info.trmode {
1347             TrByValue(lldest) => {
1348                 let llval = Load(bcx, binding_info.llmatch); // get a T*
1349                 let datum = Datum(llval, binding_info.ty, Lvalue);
1350                 bcx = datum.store_to(bcx, lldest);
1351
1352                 match opt_cleanup_scope {
1353                     None => {}
1354                     Some(s) => {
1355                         fcx.schedule_drop_mem(s, lldest, binding_info.ty);
1356                     }
1357                 }
1358             }
1359             TrByRef => {}
1360         }
1361     }
1362     return bcx;
1363 }
1364
1365 fn insert_lllocals<'a>(bcx: &'a Block<'a>,
1366                        bindings_map: &BindingsMap,
1367                        cleanup_scope: cleanup::ScopeId)
1368                        -> &'a Block<'a> {
1369     /*!
1370      * For each binding in `data.bindings_map`, adds an appropriate entry into
1371      * the `fcx.lllocals` map, scheduling cleanup in `cleanup_scope`.
1372      */
1373
1374     let fcx = bcx.fcx;
1375
1376     for (&ident, &binding_info) in bindings_map.iter() {
1377         let llval = match binding_info.trmode {
1378             // By value bindings: use the stack slot that we
1379             // copied/moved the value into
1380             TrByValue(lldest) => lldest,
1381
1382             // By ref binding: use the ptr into the matched value
1383             TrByRef => binding_info.llmatch
1384         };
1385
1386         let datum = Datum(llval, binding_info.ty, Lvalue);
1387         fcx.schedule_drop_mem(cleanup_scope, llval, binding_info.ty);
1388
1389         {
1390             debug!("binding {:?} to {}",
1391                    binding_info.id,
1392                    bcx.val_to_str(llval));
1393             let mut llmap = bcx.fcx.lllocals.borrow_mut();
1394             llmap.get().insert(binding_info.id, datum);
1395         }
1396
1397         if bcx.sess().opts.debuginfo == FullDebugInfo {
1398             debuginfo::create_match_binding_metadata(bcx,
1399                                                      ident,
1400                                                      binding_info.id,
1401                                                      binding_info.span,
1402                                                      datum);
1403         }
1404     }
1405     bcx
1406 }
1407
1408 fn compile_guard<'r,
1409                  'b>(
1410                  bcx: &'b Block<'b>,
1411                  guard_expr: &ast::Expr,
1412                  data: &ArmData,
1413                  m: &[Match<'r,'b>],
1414                  vals: &[ValueRef],
1415                  chk: &FailureHandler)
1416                  -> &'b Block<'b> {
1417     debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})",
1418            bcx.to_str(),
1419            bcx.expr_to_str(guard_expr),
1420            m.repr(bcx.tcx()),
1421            vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
1422     let _indenter = indenter();
1423
1424     // Lest the guard itself should fail, introduce a temporary cleanup
1425     // scope for any non-ref bindings we create.
1426     let temp_scope = bcx.fcx.push_custom_cleanup_scope();
1427
1428     let mut bcx = bcx;
1429     bcx = store_non_ref_bindings(bcx, data.bindings_map,
1430                                  Some(cleanup::CustomScope(temp_scope)));
1431     bcx = insert_lllocals(bcx, data.bindings_map,
1432                           cleanup::CustomScope(temp_scope));
1433
1434     let val = unpack_datum!(bcx, expr::trans(bcx, guard_expr));
1435     let val = val.to_llbool(bcx);
1436
1437     // Cancel cleanups now that the guard successfully executed.  If
1438     // the guard was false, we will drop the values explicitly
1439     // below. Otherwise, we'll add lvalue cleanups at the end.
1440     bcx.fcx.pop_custom_cleanup_scope(temp_scope);
1441
1442     return with_cond(bcx, Not(bcx, val), |bcx| {
1443         // Guard does not match: free the values we copied,
1444         // and remove all bindings from the lllocals table
1445         let bcx = drop_bindings(bcx, data);
1446         compile_submatch(bcx, m, vals, chk);
1447         bcx
1448     });
1449
1450     fn drop_bindings<'a>(bcx: &'a Block<'a>, data: &ArmData)
1451                      -> &'a Block<'a> {
1452         let mut bcx = bcx;
1453         for (_, &binding_info) in data.bindings_map.iter() {
1454             match binding_info.trmode {
1455                 TrByValue(llval) => {
1456                     bcx = glue::drop_ty(bcx, llval, binding_info.ty);
1457                 }
1458                 TrByRef => {}
1459             }
1460             let mut lllocals = bcx.fcx.lllocals.borrow_mut();
1461             lllocals.get().remove(&binding_info.id);
1462         }
1463         return bcx;
1464     }
1465 }
1466
1467 fn compile_submatch<'r,
1468                     'b>(
1469                     bcx: &'b Block<'b>,
1470                     m: &[Match<'r,'b>],
1471                     vals: &[ValueRef],
1472                     chk: &FailureHandler) {
1473     debug!("compile_submatch(bcx={}, m={}, vals={})",
1474            bcx.to_str(),
1475            m.repr(bcx.tcx()),
1476            vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
1477     let _indenter = indenter();
1478
1479     /*
1480       For an empty match, a fall-through case must exist
1481      */
1482     assert!((m.len() > 0u || chk.is_fallible()));
1483     let _icx = push_ctxt("match::compile_submatch");
1484     let mut bcx = bcx;
1485     if m.len() == 0u {
1486         Br(bcx, chk.handle_fail());
1487         return;
1488     }
1489     if m[0].pats.len() == 0u {
1490         let data = &m[0].data;
1491         for &(ref ident, ref value_ptr) in m[0].bound_ptrs.iter() {
1492             let llmatch = data.bindings_map.get(ident).llmatch;
1493             Store(bcx, *value_ptr, llmatch);
1494         }
1495         match data.arm.guard {
1496             Some(guard_expr) => {
1497                 bcx = compile_guard(bcx,
1498                                     guard_expr,
1499                                     &m[0].data,
1500                                     m.slice(1, m.len()),
1501                                     vals,
1502                                     chk);
1503             }
1504             _ => ()
1505         }
1506         Br(bcx, data.bodycx.llbb);
1507         return;
1508     }
1509
1510     let col = pick_col(m);
1511     let val = vals[col];
1512
1513     if has_nested_bindings(m, col) {
1514         let expanded = expand_nested_bindings(bcx, m, col, val);
1515         compile_submatch_continue(bcx, expanded, vals, chk, col, val)
1516     } else {
1517         compile_submatch_continue(bcx, m, vals, chk, col, val)
1518     }
1519 }
1520
1521 fn compile_submatch_continue<'r,
1522                              'b>(
1523                              mut bcx: &'b Block<'b>,
1524                              m: &[Match<'r,'b>],
1525                              vals: &[ValueRef],
1526                              chk: &FailureHandler,
1527                              col: uint,
1528                              val: ValueRef) {
1529     let fcx = bcx.fcx;
1530     let tcx = bcx.tcx();
1531     let dm = tcx.def_map;
1532
1533     let vals_left = vec::append(vals.slice(0u, col).to_owned(),
1534                                 vals.slice(col + 1u, vals.len()));
1535     let ccx = bcx.fcx.ccx;
1536     let mut pat_id = 0;
1537     for br in m.iter() {
1538         // Find a real id (we're adding placeholder wildcard patterns, but
1539         // each column is guaranteed to have at least one real pattern)
1540         if pat_id == 0 {
1541             pat_id = br.pats[col].id;
1542         }
1543     }
1544
1545     // If we are not matching against an `@T`, we should not be
1546     // required to root any values.
1547     assert!(!pats_require_rooting(bcx, m, col));
1548
1549     match collect_record_or_struct_fields(bcx, m, col) {
1550         Some(ref rec_fields) => {
1551             let pat_ty = node_id_type(bcx, pat_id);
1552             let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
1553             expr::with_field_tys(tcx, pat_ty, Some(pat_id), |discr, field_tys| {
1554                 let rec_vals = rec_fields.map(|field_name| {
1555                         let ix = ty::field_idx_strict(tcx, field_name.name, field_tys);
1556                         adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
1557                         });
1558                 compile_submatch(
1559                         bcx,
1560                         enter_rec_or_struct(bcx, dm, m, col, *rec_fields, val),
1561                         vec::append(rec_vals, vals_left),
1562                         chk);
1563             });
1564             return;
1565         }
1566         None => {}
1567     }
1568
1569     if any_tup_pat(m, col) {
1570         let tup_ty = node_id_type(bcx, pat_id);
1571         let tup_repr = adt::represent_type(bcx.ccx(), tup_ty);
1572         let n_tup_elts = match ty::get(tup_ty).sty {
1573           ty::ty_tup(ref elts) => elts.len(),
1574           _ => ccx.sess.bug("non-tuple type in tuple pattern")
1575         };
1576         let tup_vals = vec::from_fn(n_tup_elts, |i| {
1577             adt::trans_field_ptr(bcx, tup_repr, val, 0, i)
1578         });
1579         compile_submatch(bcx, enter_tup(bcx, dm, m, col, val, n_tup_elts),
1580                          vec::append(tup_vals, vals_left), chk);
1581         return;
1582     }
1583
1584     if any_tuple_struct_pat(bcx, m, col) {
1585         let struct_ty = node_id_type(bcx, pat_id);
1586         let struct_element_count;
1587         match ty::get(struct_ty).sty {
1588             ty::ty_struct(struct_id, _) => {
1589                 struct_element_count =
1590                     ty::lookup_struct_fields(tcx, struct_id).len();
1591             }
1592             _ => {
1593                 ccx.sess.bug("non-struct type in tuple struct pattern");
1594             }
1595         }
1596
1597         let struct_repr = adt::represent_type(bcx.ccx(), struct_ty);
1598         let llstructvals = vec::from_fn(struct_element_count, |i| {
1599             adt::trans_field_ptr(bcx, struct_repr, val, 0, i)
1600         });
1601         compile_submatch(bcx,
1602                          enter_tuple_struct(bcx, dm, m, col, val,
1603                                             struct_element_count),
1604                          vec::append(llstructvals, vals_left),
1605                          chk);
1606         return;
1607     }
1608
1609     if any_uniq_pat(m, col) {
1610         let llbox = Load(bcx, val);
1611         compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
1612                          vec::append(~[llbox], vals_left), chk);
1613         return;
1614     }
1615
1616     if any_region_pat(m, col) {
1617         let loaded_val = Load(bcx, val);
1618         compile_submatch(bcx, enter_region(bcx, dm, m, col, val),
1619                          vec::append(~[loaded_val], vals_left), chk);
1620         return;
1621     }
1622
1623     // Decide what kind of branch we need
1624     let opts = get_options(bcx, m, col);
1625     debug!("options={:?}", opts);
1626     let mut kind = no_branch;
1627     let mut test_val = val;
1628     debug!("test_val={}", bcx.val_to_str(test_val));
1629     if opts.len() > 0u {
1630         match opts[0] {
1631             var(_, repr) => {
1632                 let (the_kind, val_opt) = adt::trans_switch(bcx, repr, val);
1633                 kind = the_kind;
1634                 for &tval in val_opt.iter() { test_val = tval; }
1635             }
1636             lit(_) => {
1637                 let pty = node_id_type(bcx, pat_id);
1638                 test_val = load_if_immediate(bcx, val, pty);
1639                 kind = if ty::type_is_integral(pty) { switch }
1640                 else { compare };
1641             }
1642             range(_, _) => {
1643                 test_val = Load(bcx, val);
1644                 kind = compare;
1645             },
1646             vec_len(..) => {
1647                 let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
1648                 let (_, len) = tvec::get_base_and_len(bcx, val, vt.vec_ty);
1649                 test_val = len;
1650                 kind = compare_vec_len;
1651             }
1652         }
1653     }
1654     for o in opts.iter() {
1655         match *o {
1656             range(_, _) => { kind = compare; break }
1657             _ => ()
1658         }
1659     }
1660     let else_cx = match kind {
1661         no_branch | single => bcx,
1662         _ => bcx.fcx.new_temp_block("match_else")
1663     };
1664     let sw = if kind == switch {
1665         Switch(bcx, test_val, else_cx.llbb, opts.len())
1666     } else {
1667         C_int(ccx, 0) // Placeholder for when not using a switch
1668     };
1669
1670     let defaults = enter_default(else_cx, dm, m, col, val, chk);
1671     let exhaustive = chk.is_infallible() && defaults.len() == 0u;
1672     let len = opts.len();
1673
1674     // Compile subtrees for each option
1675     for (i, opt) in opts.iter().enumerate() {
1676         // In some cases in vector pattern matching, we need to override
1677         // the failure case so that instead of failing, it proceeds to
1678         // try more matching. branch_chk, then, is the proper failure case
1679         // for the current conditional branch.
1680         let mut branch_chk = None;
1681         let mut opt_cx = else_cx;
1682         if !exhaustive || i+1 < len {
1683             opt_cx = bcx.fcx.new_temp_block("match_case");
1684             match kind {
1685               single => Br(bcx, opt_cx.llbb),
1686               switch => {
1687                   match trans_opt(bcx, opt) {
1688                       single_result(r) => {
1689                         unsafe {
1690                           llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
1691                           bcx = r.bcx;
1692                         }
1693                       }
1694                       _ => {
1695                           bcx.sess().bug(
1696                               "in compile_submatch, expected \
1697                                trans_opt to return a single_result")
1698                       }
1699                   }
1700               }
1701               compare => {
1702                   let t = node_id_type(bcx, pat_id);
1703                   let Result {bcx: after_cx, val: matches} = {
1704                       match trans_opt(bcx, opt) {
1705                           single_result(Result {bcx, val}) => {
1706                               compare_values(bcx, test_val, val, t)
1707                           }
1708                           lower_bound(Result {bcx, val}) => {
1709                               compare_scalar_types(
1710                                   bcx, test_val, val,
1711                                   t, ast::BiGe)
1712                           }
1713                           range_result(Result {val: vbegin, ..},
1714                                        Result {bcx, val: vend}) => {
1715                               let Result {bcx, val: llge} =
1716                                   compare_scalar_types(
1717                                   bcx, test_val,
1718                                   vbegin, t, ast::BiGe);
1719                               let Result {bcx, val: llle} =
1720                                   compare_scalar_types(
1721                                   bcx, test_val, vend,
1722                                   t, ast::BiLe);
1723                               rslt(bcx, And(bcx, llge, llle))
1724                           }
1725                       }
1726                   };
1727                   bcx = fcx.new_temp_block("compare_next");
1728                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
1729               }
1730               compare_vec_len => {
1731                   let Result {bcx: after_cx, val: matches} = {
1732                       match trans_opt(bcx, opt) {
1733                           single_result(
1734                               Result {bcx, val}) => {
1735                               let value = compare_scalar_values(
1736                                   bcx, test_val, val,
1737                                   signed_int, ast::BiEq);
1738                               rslt(bcx, value)
1739                           }
1740                           lower_bound(
1741                               Result {bcx, val: val}) => {
1742                               let value = compare_scalar_values(
1743                                   bcx, test_val, val,
1744                                   signed_int, ast::BiGe);
1745                               rslt(bcx, value)
1746                           }
1747                           range_result(
1748                               Result {val: vbegin, ..},
1749                               Result {bcx, val: vend}) => {
1750                               let llge =
1751                                   compare_scalar_values(
1752                                   bcx, test_val,
1753                                   vbegin, signed_int, ast::BiGe);
1754                               let llle =
1755                                   compare_scalar_values(
1756                                   bcx, test_val, vend,
1757                                   signed_int, ast::BiLe);
1758                               rslt(bcx, And(bcx, llge, llle))
1759                           }
1760                       }
1761                   };
1762                   bcx = fcx.new_temp_block("compare_vec_len_next");
1763
1764                   // If none of these subcases match, move on to the
1765                   // next condition.
1766                   branch_chk = Some(JumpToBasicBlock(bcx.llbb));
1767                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
1768               }
1769               _ => ()
1770             }
1771         } else if kind == compare || kind == compare_vec_len {
1772             Br(bcx, else_cx.llbb);
1773         }
1774
1775         let mut size = 0u;
1776         let mut unpacked = ~[];
1777         match *opt {
1778             var(disr_val, repr) => {
1779                 let ExtractedBlock {vals: argvals, bcx: new_bcx} =
1780                     extract_variant_args(opt_cx, repr, disr_val, val);
1781                 size = argvals.len();
1782                 unpacked = argvals;
1783                 opt_cx = new_bcx;
1784             }
1785             vec_len(n, vt, _) => {
1786                 let (n, slice) = match vt {
1787                     vec_len_ge(i) => (n + 1u, Some(i)),
1788                     vec_len_eq => (n, None)
1789                 };
1790                 let args = extract_vec_elems(opt_cx, pat_id, n,
1791                                              slice, val, test_val);
1792                 size = args.vals.len();
1793                 unpacked = args.vals.clone();
1794                 opt_cx = args.bcx;
1795             }
1796             lit(_) | range(_, _) => ()
1797         }
1798         let opt_ms = enter_opt(opt_cx, m, opt, col, size, val);
1799         let opt_vals = vec::append(unpacked, vals_left);
1800
1801         match branch_chk {
1802             None => compile_submatch(opt_cx, opt_ms, opt_vals, chk),
1803             Some(branch_chk) => {
1804                 compile_submatch(opt_cx, opt_ms, opt_vals, &branch_chk)
1805             }
1806         }
1807     }
1808
1809     // Compile the fall-through case, if any
1810     if !exhaustive {
1811         if kind == compare || kind == compare_vec_len {
1812             Br(bcx, else_cx.llbb);
1813         }
1814         if kind != single {
1815             compile_submatch(else_cx, defaults, vals_left, chk);
1816         }
1817     }
1818 }
1819
1820 pub fn trans_match<'a>(
1821                    bcx: &'a Block<'a>,
1822                    match_expr: &ast::Expr,
1823                    discr_expr: &ast::Expr,
1824                    arms: &[ast::Arm],
1825                    dest: Dest)
1826                    -> &'a Block<'a> {
1827     let _icx = push_ctxt("match::trans_match");
1828     trans_match_inner(bcx, match_expr.id, discr_expr, arms, dest)
1829 }
1830
1831 fn create_bindings_map(bcx: &Block, pat: @ast::Pat) -> BindingsMap {
1832     // Create the bindings map, which is a mapping from each binding name
1833     // to an alloca() that will be the value for that local variable.
1834     // Note that we use the names because each binding will have many ids
1835     // from the various alternatives.
1836     let ccx = bcx.ccx();
1837     let tcx = bcx.tcx();
1838     let mut bindings_map = HashMap::new();
1839     pat_bindings(tcx.def_map, pat, |bm, p_id, span, path| {
1840         let ident = path_to_ident(path);
1841         let variable_ty = node_id_type(bcx, p_id);
1842         let llvariable_ty = type_of::type_of(ccx, variable_ty);
1843
1844         let llmatch;
1845         let trmode;
1846         match bm {
1847             ast::BindByValue(_) => {
1848                 // in this case, the final type of the variable will be T,
1849                 // but during matching we need to store a *T as explained
1850                 // above
1851                 llmatch = alloca(bcx, llvariable_ty.ptr_to(), "__llmatch");
1852                 trmode = TrByValue(alloca(bcx, llvariable_ty,
1853                                           bcx.ident(ident)));
1854             }
1855             ast::BindByRef(_) => {
1856                 llmatch = alloca(bcx, llvariable_ty, bcx.ident(ident));
1857                 trmode = TrByRef;
1858             }
1859         };
1860         bindings_map.insert(ident, BindingInfo {
1861             llmatch: llmatch,
1862             trmode: trmode,
1863             id: p_id,
1864             span: span,
1865             ty: variable_ty
1866         });
1867     });
1868     return bindings_map;
1869 }
1870
1871 fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
1872                          match_id: ast::NodeId,
1873                          discr_expr: &ast::Expr,
1874                          arms: &[ast::Arm],
1875                          dest: Dest) -> &'a Block<'a> {
1876     let _icx = push_ctxt("match::trans_match_inner");
1877     let fcx = scope_cx.fcx;
1878     let mut bcx = scope_cx;
1879     let tcx = bcx.tcx();
1880
1881     let discr_datum = unpack_datum!(bcx, expr::trans_to_lvalue(bcx, discr_expr,
1882                                                                "match"));
1883     if bcx.unreachable.get() {
1884         return bcx;
1885     }
1886
1887     let mut arm_datas = ~[];
1888     let mut matches = ~[];
1889     for arm in arms.iter() {
1890         let body = fcx.new_id_block("case_body", arm.body.id);
1891         let bindings_map = create_bindings_map(bcx, *arm.pats.get(0));
1892         let arm_data = ArmData {
1893             bodycx: body,
1894             arm: arm,
1895             bindings_map: @bindings_map
1896         };
1897         arm_datas.push(arm_data.clone());
1898         for p in arm.pats.iter() {
1899             matches.push(Match {
1900                 pats: ~[*p],
1901                 data: arm_data.clone(),
1902                 bound_ptrs: ~[],
1903             });
1904         }
1905     }
1906
1907     let t = node_id_type(bcx, discr_expr.id);
1908     let chk = {
1909         if ty::type_is_empty(tcx, t) {
1910             // Special case for empty types
1911             let fail_cx = @Cell::new(None);
1912             let fail_handler = ~DynamicFailureHandler {
1913                 bcx: scope_cx,
1914                 sp: discr_expr.span,
1915                 msg: InternedString::new("scrutinizing value that can't \
1916                                           exist"),
1917                 finished: fail_cx,
1918             };
1919             DynamicFailureHandlerClass(fail_handler)
1920         } else {
1921             Infallible
1922         }
1923     };
1924     let lldiscr = discr_datum.val;
1925     compile_submatch(bcx, matches, [lldiscr], &chk);
1926
1927     let mut arm_cxs = ~[];
1928     for arm_data in arm_datas.iter() {
1929         let mut bcx = arm_data.bodycx;
1930
1931         // If this arm has a guard, then the various by-value bindings have
1932         // already been copied into their homes.  If not, we do it here.  This
1933         // is just to reduce code space.  See extensive comment at the start
1934         // of the file for more details.
1935         if arm_data.arm.guard.is_none() {
1936             bcx = store_non_ref_bindings(bcx, arm_data.bindings_map, None);
1937         }
1938
1939         // insert bindings into the lllocals map and add cleanups
1940         let cleanup_scope = fcx.push_custom_cleanup_scope();
1941         bcx = insert_lllocals(bcx, arm_data.bindings_map,
1942                               cleanup::CustomScope(cleanup_scope));
1943         bcx = expr::trans_into(bcx, arm_data.arm.body, dest);
1944         bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
1945         arm_cxs.push(bcx);
1946     }
1947
1948     bcx = scope_cx.fcx.join_blocks(match_id, arm_cxs);
1949     return bcx;
1950 }
1951
1952 enum IrrefutablePatternBindingMode {
1953     // Stores the association between node ID and LLVM value in `lllocals`.
1954     BindLocal,
1955     // Stores the association between node ID and LLVM value in `llargs`.
1956     BindArgument
1957 }
1958
1959 pub fn store_local<'a>(bcx: &'a Block<'a>,
1960                        local: &ast::Local)
1961                        -> &'a Block<'a> {
1962     /*!
1963      * Generates code for a local variable declaration like
1964      * `let <pat>;` or `let <pat> = <opt_init_expr>`.
1965      */
1966     let _icx = push_ctxt("match::store_local");
1967     let mut bcx = bcx;
1968     let tcx = bcx.tcx();
1969     let pat = local.pat;
1970     let opt_init_expr = local.init;
1971
1972     return match opt_init_expr {
1973         Some(init_expr) => {
1974             // Optimize the "let x = expr" case. This just writes
1975             // the result of evaluating `expr` directly into the alloca
1976             // for `x`. Often the general path results in similar or the
1977             // same code post-optimization, but not always. In particular,
1978             // in unsafe code, you can have expressions like
1979             //
1980             //    let x = intrinsics::uninit();
1981             //
1982             // In such cases, the more general path is unsafe, because
1983             // it assumes it is matching against a valid value.
1984             match simple_identifier(pat) {
1985                 Some(path) => {
1986                     let var_scope = cleanup::var_scope(tcx, local.id);
1987                     return mk_binding_alloca(
1988                         bcx, pat.id, path, BindLocal, var_scope, (),
1989                         |(), bcx, v, _| expr::trans_into(bcx, init_expr,
1990                                                          expr::SaveIn(v)));
1991                 }
1992
1993                 None => {}
1994             }
1995
1996             // General path.
1997             let init_datum =
1998                 unpack_datum!(bcx, expr::trans_to_lvalue(bcx, init_expr, "let"));
1999             if ty::type_is_bot(expr_ty(bcx, init_expr)) {
2000                 create_dummy_locals(bcx, pat)
2001             } else {
2002                 if bcx.sess().asm_comments() {
2003                     add_comment(bcx, "creating zeroable ref llval");
2004                 }
2005                 let var_scope = cleanup::var_scope(tcx, local.id);
2006                 bind_irrefutable_pat(bcx, pat, init_datum.val, BindLocal, var_scope)
2007             }
2008         }
2009         None => {
2010             create_dummy_locals(bcx, pat)
2011         }
2012     };
2013
2014     fn create_dummy_locals<'a>(mut bcx: &'a Block<'a>,
2015                                pat: @ast::Pat)
2016                                -> &'a Block<'a> {
2017         // create dummy memory for the variables if we have no
2018         // value to store into them immediately
2019         let tcx = bcx.tcx();
2020         pat_bindings(tcx.def_map, pat, |_, p_id, _, path| {
2021                 let scope = cleanup::var_scope(tcx, p_id);
2022                 bcx = mk_binding_alloca(
2023                     bcx, p_id, path, BindLocal, scope, (),
2024                     |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
2025             });
2026         bcx
2027     }
2028 }
2029
2030 pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
2031                      pat: @ast::Pat,
2032                      arg: Datum<Rvalue>,
2033                      arg_scope: cleanup::ScopeId)
2034                      -> &'a Block<'a> {
2035     /*!
2036      * Generates code for argument patterns like `fn foo(<pat>: T)`.
2037      * Creates entries in the `llargs` map for each of the bindings
2038      * in `pat`.
2039      *
2040      * # Arguments
2041      *
2042      * - `pat` is the argument pattern
2043      * - `llval` is a pointer to the argument value (in other words,
2044      *   if the argument type is `T`, then `llval` is a `T*`). In some
2045      *   cases, this code may zero out the memory `llval` points at.
2046      */
2047
2048     let _icx = push_ctxt("match::store_arg");
2049
2050     match simple_identifier(pat) {
2051         Some(path) => {
2052             // Generate nicer LLVM for the common case of fn a pattern
2053             // like `x: T`
2054             let arg_ty = node_id_type(bcx, pat.id);
2055             if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
2056                 && bcx.ccx().sess.opts.debuginfo != FullDebugInfo {
2057                 // Don't copy an indirect argument to an alloca, the caller
2058                 // already put it in a temporary alloca and gave it up, unless
2059                 // we emit extra-debug-info, which requires local allocas :(.
2060                 let arg_val = arg.add_clean(bcx.fcx, arg_scope);
2061                 let mut llmap = bcx.fcx.llargs.borrow_mut();
2062                 llmap.get().insert(pat.id, Datum(arg_val, arg_ty, Lvalue));
2063                 bcx
2064             } else {
2065                 mk_binding_alloca(
2066                     bcx, pat.id, path, BindArgument, arg_scope, arg,
2067                     |arg, bcx, llval, _| arg.store_to(bcx, llval))
2068             }
2069         }
2070
2071         None => {
2072             // General path. Copy out the values that are used in the
2073             // pattern.
2074             let arg = unpack_datum!(
2075                 bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope));
2076             bind_irrefutable_pat(bcx, pat, arg.val,
2077                                  BindArgument, arg_scope)
2078         }
2079     }
2080 }
2081
2082 fn mk_binding_alloca<'a,A>(bcx: &'a Block<'a>,
2083                            p_id: ast::NodeId,
2084                            path: &ast::Path,
2085                            binding_mode: IrrefutablePatternBindingMode,
2086                            cleanup_scope: cleanup::ScopeId,
2087                            arg: A,
2088                            populate: |A, &'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>)
2089                          -> &'a Block<'a> {
2090     let var_ty = node_id_type(bcx, p_id);
2091     let ident = ast_util::path_to_ident(path);
2092
2093     // Allocate memory on stack for the binding.
2094     let llval = alloc_ty(bcx, var_ty, bcx.ident(ident));
2095
2096     // Subtle: be sure that we *populate* the memory *before*
2097     // we schedule the cleanup.
2098     let bcx = populate(arg, bcx, llval, var_ty);
2099     bcx.fcx.schedule_drop_mem(cleanup_scope, llval, var_ty);
2100
2101     // Now that memory is initialized and has cleanup scheduled,
2102     // create the datum and insert into the local variable map.
2103     let datum = Datum(llval, var_ty, Lvalue);
2104     let mut llmap = match binding_mode {
2105         BindLocal => bcx.fcx.lllocals.borrow_mut(),
2106         BindArgument => bcx.fcx.llargs.borrow_mut()
2107     };
2108     llmap.get().insert(p_id, datum);
2109     bcx
2110 }
2111
2112 fn bind_irrefutable_pat<'a>(
2113                         bcx: &'a Block<'a>,
2114                         pat: @ast::Pat,
2115                         val: ValueRef,
2116                         binding_mode: IrrefutablePatternBindingMode,
2117                         cleanup_scope: cleanup::ScopeId)
2118                         -> &'a Block<'a> {
2119     /*!
2120      * A simple version of the pattern matching code that only handles
2121      * irrefutable patterns. This is used in let/argument patterns,
2122      * not in match statements. Unifying this code with the code above
2123      * sounds nice, but in practice it produces very inefficient code,
2124      * since the match code is so much more general. In most cases,
2125      * LLVM is able to optimize the code, but it causes longer compile
2126      * times and makes the generated code nigh impossible to read.
2127      *
2128      * # Arguments
2129      * - bcx: starting basic block context
2130      * - pat: the irrefutable pattern being matched.
2131      * - val: the value being matched -- must be an lvalue (by ref, with cleanup)
2132      * - binding_mode: is this for an argument or a local variable?
2133      */
2134
2135     debug!("bind_irrefutable_pat(bcx={}, pat={}, binding_mode={:?})",
2136            bcx.to_str(),
2137            pat.repr(bcx.tcx()),
2138            binding_mode);
2139
2140     if bcx.sess().asm_comments() {
2141         add_comment(bcx, format!("bind_irrefutable_pat(pat={})",
2142                               pat.repr(bcx.tcx())));
2143     }
2144
2145     let _indenter = indenter();
2146
2147     let _icx = push_ctxt("match::bind_irrefutable_pat");
2148     let mut bcx = bcx;
2149     let tcx = bcx.tcx();
2150     let ccx = bcx.ccx();
2151     match pat.node {
2152         ast::PatIdent(pat_binding_mode, ref path, inner) => {
2153             if pat_is_binding(tcx.def_map, pat) {
2154                 // Allocate the stack slot where the value of this
2155                 // binding will live and place it into the appropriate
2156                 // map.
2157                 bcx = mk_binding_alloca(
2158                     bcx, pat.id, path, binding_mode, cleanup_scope, (),
2159                     |(), bcx, llval, ty| {
2160                         match pat_binding_mode {
2161                             ast::BindByValue(_) => {
2162                                 // By value binding: move the value that `val`
2163                                 // points at into the binding's stack slot.
2164                                 let d = Datum(val, ty, Lvalue);
2165                                 d.store_to(bcx, llval)
2166                             }
2167
2168                             ast::BindByRef(_) => {
2169                                 // By ref binding: the value of the variable
2170                                 // is the pointer `val` itself.
2171                                 Store(bcx, val, llval);
2172                                 bcx
2173                             }
2174                         }
2175                     });
2176             }
2177
2178             for &inner_pat in inner.iter() {
2179                 bcx = bind_irrefutable_pat(bcx, inner_pat, val,
2180                                            binding_mode, cleanup_scope);
2181             }
2182         }
2183         ast::PatEnum(_, ref sub_pats) => {
2184             let def_map = bcx.tcx().def_map.borrow();
2185             match def_map.get().find(&pat.id) {
2186                 Some(&ast::DefVariant(enum_id, var_id, _)) => {
2187                     let repr = adt::represent_node(bcx, pat.id);
2188                     let vinfo = ty::enum_variant_with_id(ccx.tcx,
2189                                                          enum_id,
2190                                                          var_id);
2191                     let args = extract_variant_args(bcx,
2192                                                     repr,
2193                                                     vinfo.disr_val,
2194                                                     val);
2195                     for sub_pat in sub_pats.iter() {
2196                         for (i, argval) in args.vals.iter().enumerate() {
2197                             bcx = bind_irrefutable_pat(bcx, *sub_pat.get(i),
2198                                                        *argval, binding_mode,
2199                                                        cleanup_scope);
2200                         }
2201                     }
2202                 }
2203                 Some(&ast::DefFn(..)) |
2204                 Some(&ast::DefStruct(..)) => {
2205                     match *sub_pats {
2206                         None => {
2207                             // This is a unit-like struct. Nothing to do here.
2208                         }
2209                         Some(ref elems) => {
2210                             // This is the tuple struct case.
2211                             let repr = adt::represent_node(bcx, pat.id);
2212                             for (i, elem) in elems.iter().enumerate() {
2213                                 let fldptr = adt::trans_field_ptr(bcx, repr,
2214                                                                   val, 0, i);
2215                                 bcx = bind_irrefutable_pat(bcx, *elem,
2216                                                            fldptr, binding_mode,
2217                                                            cleanup_scope);
2218                             }
2219                         }
2220                     }
2221                 }
2222                 Some(&ast::DefStatic(_, false)) => {
2223                 }
2224                 _ => {
2225                     // Nothing to do here.
2226                 }
2227             }
2228         }
2229         ast::PatStruct(_, ref fields, _) => {
2230             let tcx = bcx.tcx();
2231             let pat_ty = node_id_type(bcx, pat.id);
2232             let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
2233             expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| {
2234                 for f in fields.iter() {
2235                     let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys);
2236                     let fldptr = adt::trans_field_ptr(bcx, pat_repr, val,
2237                                                       discr, ix);
2238                     bcx = bind_irrefutable_pat(bcx, f.pat, fldptr,
2239                                                binding_mode, cleanup_scope);
2240                 }
2241             })
2242         }
2243         ast::PatTup(ref elems) => {
2244             let repr = adt::represent_node(bcx, pat.id);
2245             for (i, elem) in elems.iter().enumerate() {
2246                 let fldptr = adt::trans_field_ptr(bcx, repr, val, 0, i);
2247                 bcx = bind_irrefutable_pat(bcx, *elem, fldptr,
2248                                            binding_mode, cleanup_scope);
2249             }
2250         }
2251         ast::PatUniq(inner) => {
2252             let llbox = Load(bcx, val);
2253             bcx = bind_irrefutable_pat(bcx, inner, llbox, binding_mode, cleanup_scope);
2254         }
2255         ast::PatRegion(inner) => {
2256             let loaded_val = Load(bcx, val);
2257             bcx = bind_irrefutable_pat(bcx, inner, loaded_val, binding_mode, cleanup_scope);
2258         }
2259         ast::PatVec(..) => {
2260             bcx.tcx().sess.span_bug(
2261                 pat.span,
2262                 format!("vector patterns are never irrefutable!"));
2263         }
2264         ast::PatWild | ast::PatWildMulti | ast::PatLit(_) | ast::PatRange(_, _) => ()
2265     }
2266     return bcx;
2267 }