]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #15871 : dotdash/rust/unnamed_fmtstr, r=pcwalton
authorbors <bors@rust-lang.org>
Tue, 22 Jul 2014 09:01:17 +0000 (09:01 +0000)
committerbors <bors@rust-lang.org>
Tue, 22 Jul 2014 09:01:17 +0000 (09:01 +0000)
1  2 
src/libsyntax/ext/format.rs

index 2e86d1c005d1cb416fbfe78b44cdac833821c48c,8fefd4656558983118deb5be0ebdcb3b58404784..b00924c15901612a509bf93d0f53e7e3d730f5da
@@@ -49,9 -49,6 +49,9 @@@ struct Context<'a, 'b> 
      name_types: HashMap<String, ArgumentType>,
      name_ordering: Vec<String>,
  
 +    /// The latest consecutive literal strings
 +    literal: Option<String>,
 +
      /// Collection of the compiled `rt::Piece` structures
      pieces: Vec<Gc<ast::Expr>>,
      name_positions: HashMap<String, uint>,
@@@ -319,6 -316,11 +319,11 @@@ impl<'a, 'b> Context<'a, 'b> 
      /// These attributes are applied to all statics that this syntax extension
      /// will generate.
      fn static_attrs(&self) -> Vec<ast::Attribute> {
+         // Flag statics as `inline` so LLVM can merge duplicate globals as much
+         // as possible (which we're generating a whole lot of).
+         let unnamed = self.ecx.meta_word(self.fmtsp, InternedString::new("inline"));
+         let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
          // Do not warn format string as dead code
          let dead_code = self.ecx.meta_word(self.fmtsp,
                                             InternedString::new("dead_code"));
                                                   InternedString::new("allow"),
                                                   vec!(dead_code));
          let allow_dead_code = self.ecx.attribute(self.fmtsp, allow_dead_code);
-         return vec!(allow_dead_code);
+         return vec!(unnamed, allow_dead_code);
      }
  
      fn rtpath(&self, s: &str) -> Vec<ast::Ident> {
          }
      }
  
 +    /// Translate the accumulated string literals to a static `rt::Piece`
 +    fn trans_literal_string(&mut self) -> Option<Gc<ast::Expr>> {
 +        let sp = self.fmtsp;
 +        self.literal.take().map(|s| {
 +            let s = token::intern_and_get_ident(s.as_slice());
 +            self.ecx.expr_call_global(sp,
 +                                      self.rtpath("String"),
 +                                      vec!(
 +                self.ecx.expr_str(sp, s)
 +            ))
 +        })
 +    }
 +
      /// Translate a `parse::Piece` to a static `rt::Piece`
 -    fn trans_piece(&mut self, piece: &parse::Piece) -> Gc<ast::Expr> {
 +    fn trans_piece(&mut self, piece: &parse::Piece) -> Option<Gc<ast::Expr>> {
          let sp = self.fmtsp;
          match *piece {
              parse::String(s) => {
 -                let s = token::intern_and_get_ident(s);
 -                self.ecx.expr_call_global(sp,
 -                                          self.rtpath("String"),
 -                                          vec!(
 -                    self.ecx.expr_str(sp, s)
 -                ))
 +                match self.literal {
 +                    Some(ref mut sb) => sb.push_str(s),
 +                    ref mut empty => *empty = Some(String::from_str(s)),
 +                }
 +                None
              }
              parse::Argument(ref arg) => {
                  // Translate the position
                  let s = self.ecx.expr_struct(sp, path, vec!(
                      self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
                      self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt)));
 -                self.ecx.expr_call_global(sp, self.rtpath("Argument"), vec!(s))
 +                Some(self.ecx.expr_call_global(sp, self.rtpath("Argument"), vec!(s)))
              }
          }
      }
@@@ -709,7 -699,6 +714,7 @@@ pub fn expand_preparsed_format_args(ecx
          name_ordering: name_ordering,
          nest_level: 0,
          next_arg: 0,
 +        literal: None,
          pieces: Vec::new(),
          method_statics: Vec::new(),
          fmtsp: sp,
              Some(piece) => {
                  if parser.errors.len() > 0 { break }
                  cx.verify_piece(&piece);
 -                let piece = cx.trans_piece(&piece);
 -                cx.pieces.push(piece);
 +                match cx.trans_piece(&piece) {
 +                    Some(piece) => {
 +                        cx.trans_literal_string().map(|piece|
 +                                                      cx.pieces.push(piece));
 +                        cx.pieces.push(piece);
 +                    }
 +                    None => {}
 +                }
              }
              None => break
          }
          }
          None => {}
      }
 +    cx.trans_literal_string().map(|piece| cx.pieces.push(piece));
  
      // Make sure that all arguments were used and all arguments have types.
      for (i, ty) in cx.arg_types.iter().enumerate() {