Skip to content

Commit d052912

Browse files
committed
auto merge of #9851 : alexcrichton/rust/include_bin, r=huonw
Previously an ExprLit was created *per byte* causing a huge increase in memory bloat. This adds a new `lit_binary` to contain a literal of binary data, which is currently only used by the include_bin! syntax extension. This massively speeds up compilation times of the shootout-k-nucleotide-pipes test before: time: 469s memory: 6GB assertion failure in LLVM (section too large) after: time: 2.50s memory: 124MB Closes #2598
2 parents 792d732 + 273784e commit d052912

File tree

11 files changed

+62
-18
lines changed

11 files changed

+62
-18
lines changed

doc/rust.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ explain, here's a few use cases and what they would entail.
15891589
* A crate needs a global available "helper module" to itself, but it doesn't
15901590
want to expose the helper module as a public API. To accomplish this, the root
15911591
of the crate's hierarchy would have a private module which then internally has
1592-
a "public api". Because the entire crate is an ancestor of the root, then the
1592+
a "public api". Because the entire crate is a descendant of the root, then the
15931593
entire local crate can access this private module through the second case.
15941594

15951595
* When writing unit tests for a module, it's often a common idiom to have an
@@ -1602,7 +1602,10 @@ In the second case, it mentions that a private item "can be accessed" by the
16021602
current module and its descendants, but the exact meaning of accessing an item
16031603
depends on what the item is. Accessing a module, for example, would mean looking
16041604
inside of it (to import more items). On the other hand, accessing a function
1605-
would mean that it is invoked.
1605+
would mean that it is invoked. Additionally, path expressions and import
1606+
statements are considered to access an item in the sense that the
1607+
import/expression is only valid if the destination is in the current visibility
1608+
scope.
16061609

16071610
Here's an example of a program which exemplifies the three cases outlined above.
16081611

src/librustc/middle/const_eval.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ pub enum const_val {
297297
const_int(i64),
298298
const_uint(u64),
299299
const_str(@str),
300+
const_binary(@[u8]),
300301
const_bool(bool)
301302
}
302303

@@ -476,6 +477,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
476477
pub fn lit_to_const(lit: &lit) -> const_val {
477478
match lit.node {
478479
lit_str(s, _) => const_str(s),
480+
lit_binary(data) => const_binary(data),
479481
lit_char(n) => const_uint(n as u64),
480482
lit_int(n, _) => const_int(n),
481483
lit_uint(n, _) => const_uint(n),

src/librustc/middle/trans/common.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,24 @@ pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
917917
}
918918
}
919919

920+
pub fn C_binary_slice(cx: &mut CrateContext, data: &[u8]) -> ValueRef {
921+
unsafe {
922+
let len = data.len();
923+
let lldata = C_bytes(data);
924+
925+
let gsym = token::gensym("binary");
926+
let g = do format!("binary{}", gsym).with_c_str |buf| {
927+
llvm::LLVMAddGlobal(cx.llmod, val_ty(lldata).to_ref(), buf)
928+
};
929+
llvm::LLVMSetInitializer(g, lldata);
930+
llvm::LLVMSetGlobalConstant(g, True);
931+
lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
932+
933+
let cs = llvm::LLVMConstPointerCast(g, Type::i8p().to_ref());
934+
C_struct([cs, C_uint(cx, len)], false)
935+
}
936+
}
937+
920938
pub fn C_zero_byte_arr(size: uint) -> ValueRef {
921939
unsafe {
922940
let mut i = 0u;

src/librustc/middle/trans/consts.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ pub fn const_lit(cx: &mut CrateContext, e: &ast::Expr, lit: ast::lit)
7171
}
7272
ast::lit_bool(b) => C_bool(b),
7373
ast::lit_nil => C_nil(),
74-
ast::lit_str(s, _) => C_estr_slice(cx, s)
74+
ast::lit_str(s, _) => C_estr_slice(cx, s),
75+
ast::lit_binary(data) => C_binary_slice(cx, data),
7576
}
7677
}
7778

src/librustc/middle/ty.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4442,6 +4442,12 @@ pub fn eval_repeat_count<T: ExprTyProvider>(tcx: &T, count_expr: &ast::Expr) ->
44424442
repeat count but found boolean");
44434443
return 0;
44444444
}
4445+
const_eval::const_binary(_) => {
4446+
tcx.ty_ctxt().sess.span_err(count_expr.span,
4447+
"expected positive integer for \
4448+
repeat count but found binary array");
4449+
return 0;
4450+
}
44454451
},
44464452
Err(*) => {
44474453
tcx.ty_ctxt().sess.span_err(count_expr.span,

src/librustc/middle/typeck/check/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,10 @@ pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t {
10201020

10211021
match lit.node {
10221022
ast::lit_str(*) => ty::mk_estr(tcx, ty::vstore_slice(ty::re_static)),
1023+
ast::lit_binary(*) => {
1024+
ty::mk_evec(tcx, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable },
1025+
ty::vstore_slice(ty::re_static))
1026+
}
10231027
ast::lit_char(_) => ty::mk_char(),
10241028
ast::lit_int(_, t) => ty::mk_mach_int(t),
10251029
ast::lit_uint(_, t) => ty::mk_mach_uint(t),

src/librustdoc/clean.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ impl ToSource for syntax::codemap::Span {
11211121
fn lit_to_str(lit: &ast::lit) -> ~str {
11221122
match lit.node {
11231123
ast::lit_str(st, _) => st.to_owned(),
1124+
ast::lit_binary(data) => format!("{:?}", data.as_slice()),
11241125
ast::lit_char(c) => ~"'" + std::char::from_u32(c).unwrap().to_str() + "'",
11251126
ast::lit_int(i, _t) => i.to_str(),
11261127
ast::lit_uint(u, _t) => u.to_str(),

src/libsyntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,7 @@ pub type lit = Spanned<lit_>;
691691
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
692692
pub enum lit_ {
693693
lit_str(@str, StrStyle),
694+
lit_binary(@[u8]),
694695
lit_char(u32),
695696
lit_int(i64, int_ty),
696697
lit_uint(u64, uint_ty),

src/libsyntax/ext/source_util.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,19 @@ pub fn expand_include_str(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
101101
}
102102

103103
pub fn expand_include_bin(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
104-
-> base::MacResult {
104+
-> base::MacResult
105+
{
106+
use std::at_vec;
107+
105108
let file = get_single_str_from_tts(cx, sp, tts, "include_bin!");
106109
match io::read_whole_file(&res_rel_file(cx, sp, &Path::new(file))) {
107-
result::Ok(src) => {
108-
let u8_exprs: ~[@ast::Expr] = src.iter().map(|char| cx.expr_u8(sp, *char)).collect();
109-
base::MRExpr(cx.expr_vec(sp, u8_exprs))
110-
}
111-
result::Err(ref e) => {
112-
cx.parse_sess().span_diagnostic.handler().fatal((*e))
113-
}
110+
result::Ok(src) => {
111+
let v = at_vec::to_managed_move(src);
112+
base::MRExpr(cx.expr_lit(sp, ast::lit_binary(v)))
113+
}
114+
result::Err(ref e) => {
115+
cx.parse_sess().span_diagnostic.handler().fatal((*e))
116+
}
114117
}
115118
}
116119

src/libsyntax/print/pprust.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,14 @@ pub fn print_literal(s: @ps, lit: &ast::lit) {
20922092
ast::lit_bool(val) => {
20932093
if val { word(s.s, "true"); } else { word(s.s, "false"); }
20942094
}
2095+
ast::lit_binary(arr) => {
2096+
ibox(s, indent_unit);
2097+
word(s.s, "[");
2098+
commasep_cmnt(s, inconsistent, arr, |s, u| word(s.s, format!("{}", *u)),
2099+
|_| lit.span);
2100+
word(s.s, "]");
2101+
end(s);
2102+
}
20952103
}
20962104
}
20972105

src/test/bench/shootout-k-nucleotide-pipes.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,14 @@ fn make_sequence_processor(sz: uint,
156156
157157
// given a FASTA file on stdin, process sequence THREE
158158
fn main() {
159-
use std::rt::io::{Reader, Open};
160-
use std::rt::io::file::FileInfo;
159+
use std::rt::io::Reader;
161160
use std::rt::io::native::stdio;
161+
use std::rt::io::mem::MemReader;
162162
use std::rt::io::buffered::BufferedReader;
163163
164164
let rdr = if os::getenv("RUST_BENCH").is_some() {
165-
// FIXME: Using this compile-time env variable is a crummy way to
166-
// get to this massive data set, but include_bin! chokes on it (#2598)
167-
let mut path = Path::new(env!("CFG_SRC_DIR"));
168-
path.push("src/test/bench/shootout-k-nucleotide.data");
169-
~path.open_reader(Open).unwrap() as ~Reader
165+
let foo = include_bin!("shootout-k-nucleotide.data");
166+
~MemReader::new(foo.to_owned()) as ~Reader
170167
} else {
171168
~stdio::stdin() as ~Reader
172169
};

0 commit comments

Comments
 (0)