summaryrefslogtreecommitdiff
path: root/src/codegen/helpers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/helpers.rs')
-rw-r--r--src/codegen/helpers.rs113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
new file mode 100644
index 00000000..e2fc1120
--- /dev/null
+++ b/src/codegen/helpers.rs
@@ -0,0 +1,113 @@
+/// Helpers for code generation that don't need macro expansion.
+
+use aster;
+use ir::layout::Layout;
+use syntax::ast;
+use syntax::codemap::respan;
+use syntax::ptr::P;
+
+
+pub mod attributes {
+ use aster;
+ use syntax::ast;
+
+ pub fn repr(which: &str) -> ast::Attribute {
+ aster::AstBuilder::new().attr().list("repr").words(&[which]).build()
+ }
+
+ pub fn repr_list(which_ones: &[&str]) -> ast::Attribute {
+ aster::AstBuilder::new().attr().list("repr").words(which_ones).build()
+ }
+
+ pub fn derives(which_ones: &[&str]) -> ast::Attribute {
+ aster::AstBuilder::new().attr().list("derive").words(which_ones).build()
+ }
+
+ pub fn inline() -> ast::Attribute {
+ aster::AstBuilder::new().attr().word("inline")
+ }
+
+ pub fn doc(comment: &str) -> ast::Attribute {
+ aster::AstBuilder::new().attr().doc(comment)
+ }
+
+ pub fn link_name(name: &str) -> ast::Attribute {
+ aster::AstBuilder::new().attr().name_value("link_name").str(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 struct BlobTyBuilder {
+ layout: Layout,
+}
+
+impl BlobTyBuilder {
+ pub fn new(layout: Layout) -> Self {
+ BlobTyBuilder {
+ layout: layout,
+ }
+ }
+
+ pub fn build(self) -> P<ast::Ty> {
+ use std::cmp;
+
+ let ty_name = match self.layout.align {
+ 8 => "u64",
+ 4 => "u32",
+ 2 => "u16",
+ 1 | _ => "u8",
+ };
+ let data_len = if ty_name == "u8" {
+ self.layout.size
+ } else {
+ self.layout.size / cmp::max(self.layout.align, 1)
+ };
+
+ let inner_ty = aster::AstBuilder::new().ty().path().id(ty_name).build();
+ if data_len == 1 {
+ inner_ty
+ } else {
+ ArrayTyBuilder::new().with_len(data_len).build(inner_ty)
+ }
+ }
+}
+
+pub struct ArrayTyBuilder {
+ len: usize,
+}
+
+impl ArrayTyBuilder {
+ pub fn new() -> Self {
+ ArrayTyBuilder {
+ len: 0,
+ }
+ }
+
+ pub fn with_len(mut self, len: usize) -> Self {
+ self.len = len;
+ self
+ }
+
+ pub fn build(self, ty: P<ast::Ty>) -> P<ast::Ty> {
+ use syntax::codemap::DUMMY_SP;
+ let size =
+ ast::LitKind::Int(self.len as u64,
+ ast::LitIntType::Unsigned(ast::UintTy::Us));
+ let size = ast::ExprKind::Lit(P(respan(DUMMY_SP, size)));
+ let array_kind = ast::TyKind::FixedLengthVec(ty,
+ P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ node: size,
+ span: DUMMY_SP,
+ attrs: ast::ThinVec::new(),
+ })
+ );
+
+ P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: array_kind,
+ span: DUMMY_SP,
+ })
+ }
+}