summaryrefslogtreecommitdiff
path: root/src/codegen/helpers.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-09-07 14:02:09 -0500
committerGitHub <noreply@github.com>2017-09-07 14:02:09 -0500
commitb13f0766e28cf75dd04f358bf64d87ea96b111c3 (patch)
treed8686bf93e5fa8c52ff6d085008a6b25c2cba42e /src/codegen/helpers.rs
parentdcd8385a41f6fd6d8f5208931c418cbc745672b4 (diff)
parent46f74c189c95fc6a41daf8ded741e0cf5f5bed92 (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.rs208
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()
}
}