diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-09-07 14:02:09 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-07 14:02:09 -0500 |
commit | b13f0766e28cf75dd04f358bf64d87ea96b111c3 (patch) | |
tree | d8686bf93e5fa8c52ff6d085008a6b25c2cba42e /src/codegen/helpers.rs | |
parent | dcd8385a41f6fd6d8f5208931c418cbc745672b4 (diff) | |
parent | 46f74c189c95fc6a41daf8ded741e0cf5f5bed92 (diff) |
Auto merge of #940 - fitzgen:no-syntex, r=emilio
No more syntex
There are a few commits in this PR, but the big one is the commit that goes `syntex` -> `quote` for code generation. I've included a copy of its commit message below.
I tried to verify that it works with the stylo build still, but there were some issues, and then I checked with master, and that wasn't working either. So now I'm C-Reducing the failures on master and figured that this is at least ready for feedback in the meantime.
r? @emilio
----------------------------
The `syntex` crate is unmaintained. It is slow to build, and additionally it requires that we pre-process `src/codegen/mod.rs` before we build the `bindgen` crate.
The `quote` crate provides similar quasi-quoting functionality, is maintained, and builds faster. It doesn't have a typed API or builders, however; it only deals with tokens.
Before this commit:
```
$ cargo clean; cargo build
<snip>
Finished dev [unoptimized + debuginfo] target(s) in 98.75 secs
```
After this commit:
```
$ cargo clean; cargo build
<snip>
Finished dev [unoptimized + debuginfo] target(s) in 46.26 secs
```
Build time is cut in half! But what about run time?
Before this commit:
```
Generated Stylo bindings in: Duration { secs: 3, nanos: 521105668 }
```
After this commit:
```
Generated Stylo bindings in: Duration { secs: 3, nanos: 548797242 }
```
So it appears to be about 20ms slower at generating Stylo bindings, but I suspect this is well within the noise.
Finally, this also lets us remove that nasty `mem::transmute` inside `bindgen::ir::BindgenContext::gen` that was used for the old `syntex` context. Now `BindgenContext` doesn't have a lifetime parameter either. This should make it easier to revisit doing our analyses in parallel with `rayon`, since that context was one of the things that made it hard for `BindgenContext` to implement `Sync`.
Fixes #925
Diffstat (limited to 'src/codegen/helpers.rs')
-rw-r--r-- | src/codegen/helpers.rs | 208 |
1 files changed, 101 insertions, 107 deletions
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs index ed165aa9..5136d787 100644 --- a/src/codegen/helpers.rs +++ b/src/codegen/helpers.rs @@ -1,66 +1,59 @@ //! Helpers for code generation that don't need macro expansion. -use aster; use ir::layout::Layout; -use syntax::ast; -use syntax::ptr::P; - +use quote; pub mod attributes { - use aster; - use syntax::ast; - - pub fn allow(which_ones: &[&str]) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("allow") - .words(which_ones) - .build() - } + use quote; - pub fn repr(which: &str) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("repr") - .words(&[which]) - .build() + pub fn repr(which: &str) -> quote::Tokens { + let which = quote::Ident::new(which); + quote! { + #[repr( #which )] + } } - pub fn repr_list(which_ones: &[&str]) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("repr") - .words(which_ones) - .build() + pub fn repr_list(which_ones: &[&str]) -> quote::Tokens { + let which_ones = which_ones.iter().cloned().map(quote::Ident::new); + quote! { + #[repr( #( #which_ones ),* )] + } } - pub fn derives(which_ones: &[&str]) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("derive") - .words(which_ones) - .build() + pub fn derives(which_ones: &[&str]) -> quote::Tokens { + let which_ones = which_ones.iter().cloned().map(quote::Ident::new); + quote! { + #[derive( #( #which_ones ),* )] + } } - pub fn inline() -> ast::Attribute { - aster::AstBuilder::new().attr().word("inline") + pub fn inline() -> quote::Tokens { + quote! { + #[inline] + } } - pub fn doc(comment: String) -> ast::Attribute { - aster::AstBuilder::new().attr().doc(&*comment) + pub fn doc(comment: String) -> quote::Tokens { + // Doc comments are already preprocessed into nice `///` formats by the + // time they get here. Just make sure that we have newlines around it so + // that nothing else gets wrapped into the comment. + let mut tokens = quote! {}; + tokens.append("\n"); + tokens.append(comment); + tokens.append("\n"); + tokens } - pub fn link_name(name: &str) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .name_value("link_name") - .str(name) + pub fn link_name(name: &str) -> quote::Tokens { + quote! { + #[link_name = #name] + } } } /// Generates a proper type for a field or type with a given `Layout`, that is, /// a type with the correct size and alignment restrictions. -pub fn blob(layout: Layout) -> P<ast::Ty> { +pub fn blob(layout: Layout) -> quote::Tokens { let opaque = layout.opaque(); // FIXME(emilio, #412): We fall back to byte alignment, but there are @@ -75,39 +68,46 @@ pub fn blob(layout: Layout) -> P<ast::Ty> { } }; + let ty_name = quote::Ident::new(ty_name); + let data_len = opaque.array_size().unwrap_or(layout.size); - let inner_ty = aster::AstBuilder::new().ty().path().id(ty_name).build(); if data_len == 1 { - inner_ty + quote! { + #ty_name + } } else { - aster::ty::TyBuilder::new().array(data_len).build(inner_ty) + quote! { + [ #ty_name ; #data_len ] + } } } pub mod ast_ty { - use aster; use ir::context::BindgenContext; use ir::function::FunctionSig; use ir::ty::FloatKind; - use syntax::ast; - use syntax::ptr::P; + use quote; - pub fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> { - let ident = ctx.rust_ident_raw(&name); + pub fn raw_type(ctx: &BindgenContext, name: &str) -> quote::Tokens { + let ident = ctx.rust_ident_raw(name); match ctx.options().ctypes_prefix { Some(ref prefix) => { - let prefix = ctx.rust_ident_raw(prefix); - quote_ty!(ctx.ext_cx(), $prefix::$ident) + let prefix = ctx.rust_ident_raw(prefix.as_str()); + quote! { + #prefix::#ident + } } - None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident), + None => quote! { + ::std::os::raw::#ident + }, } } pub fn float_kind_rust_type( ctx: &BindgenContext, fk: FloatKind, - ) -> P<ast::Ty> { + ) -> quote::Tokens { // TODO: we probably should just take the type layout into // account? // @@ -116,64 +116,50 @@ pub mod ast_ty { // FIXME: `c_longdouble` doesn't seem to be defined in some // systems, so we use `c_double` directly. match (fk, ctx.options().convert_floats) { - (FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(), + (FloatKind::Float, true) => quote! { f32 }, (FloatKind::Double, true) | - (FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(), + (FloatKind::LongDouble, true) => quote! { f64 }, (FloatKind::Float, false) => raw_type(ctx, "c_float"), (FloatKind::Double, false) | (FloatKind::LongDouble, false) => raw_type(ctx, "c_double"), - (FloatKind::Float128, _) => { - aster::ty::TyBuilder::new().array(16).u8() - } + (FloatKind::Float128, _) => quote! { [u8; 16] }, } } - pub fn int_expr(val: i64) -> P<ast::Expr> { - use std::i64; - let expr = aster::AstBuilder::new().expr(); - - // This is not representable as an i64 if it's negative, so we - // special-case it. - // - // Fix in aster incoming. - if val == i64::MIN { - expr.neg().uint(1u64 << 63) - } else { - expr.int(val) - } + pub fn int_expr(val: i64) -> quote::Tokens { + // Don't use quote! { #val } because that adds the type suffix. + let mut tokens = quote! {}; + tokens.append(val.to_string()); + tokens } - pub fn bool_expr(val: bool) -> P<ast::Expr> { - aster::AstBuilder::new().expr().bool(val) + pub fn uint_expr(val: u64) -> quote::Tokens { + // Don't use quote! { #val } because that adds the type suffix. + let mut tokens = quote! {}; + tokens.append(val.to_string()); + tokens } - pub fn byte_array_expr(bytes: &[u8]) -> P<ast::Expr> { - let mut vec = Vec::with_capacity(bytes.len() + 1); - for byte in bytes { - vec.push(int_expr(*byte as i64)); + pub fn byte_array_expr(bytes: &[u8]) -> quote::Tokens { + let mut bytes: Vec<_> = bytes.iter().cloned().collect(); + bytes.push(0); + quote! { + #bytes } - vec.push(int_expr(0)); - - let kind = ast::ExprKind::Array(vec); - - aster::AstBuilder::new().expr().build_expr_kind(kind) } - pub fn cstr_expr(mut string: String) -> P<ast::Expr> { + pub fn cstr_expr(mut string: String) -> quote::Tokens { string.push('\0'); - aster::AstBuilder::new().expr().build_lit( - aster::AstBuilder::new() - .lit() - .byte_str(string), - ) + let b = quote::ByteStr(&string); + quote! { + #b + } } pub fn float_expr( ctx: &BindgenContext, f: f64, - ) -> Result<P<ast::Expr>, ()> { - use aster::symbol::ToSymbol; - + ) -> Result<quote::Tokens, ()> { if f.is_finite() { let mut string = f.to_string(); @@ -182,21 +168,28 @@ pub mod ast_ty { string.push('.'); } - let kind = - ast::LitKind::FloatUnsuffixed(string.as_str().to_symbol()); - return Ok(aster::AstBuilder::new().expr().lit().build_lit(kind)); + let mut tokens = quote! {}; + tokens.append(string); + return Ok(tokens); } let prefix = ctx.trait_prefix(); + if f.is_nan() { - return Ok(quote_expr!(ctx.ext_cx(), ::$prefix::f64::NAN)); + return Ok(quote! { + ::#prefix::f64::NAN + }); } if f.is_infinite() { return Ok(if f.is_sign_positive() { - quote_expr!(ctx.ext_cx(), ::$prefix::f64::INFINITY) + quote! { + ::#prefix::f64::INFINITY + } } else { - quote_expr!(ctx.ext_cx(), ::$prefix::f64::NEG_INFINITY) + quote! { + ::#prefix::f64::NEG_INFINITY + } }); } @@ -207,23 +200,24 @@ pub mod ast_ty { pub fn arguments_from_signature( signature: &FunctionSig, ctx: &BindgenContext, - ) -> Vec<P<ast::Expr>> { - // TODO: We need to keep in sync the argument names, so we should unify - // this with the other loop that decides them. + ) -> Vec<quote::Tokens> { let mut unnamed_arguments = 0; signature .argument_types() .iter() .map(|&(ref name, _ty)| { - let arg_name = match *name { - Some(ref name) => ctx.rust_mangle(name).into_owned(), + match *name { + Some(ref name) => { + let name = ctx.rust_ident(name); + quote! { #name } + } None => { unnamed_arguments += 1; - format!("arg{}", unnamed_arguments) + let name = ctx.rust_ident(format!("arg{}", unnamed_arguments)); + quote! { #name } } - }; - aster::expr::ExprBuilder::new().id(arg_name) + } }) - .collect::<Vec<_>>() + .collect() } } |