about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-03-12 07:51:54 -0700
committerbors <bors@rust-lang.org>2013-03-12 07:51:54 -0700
commit34aaf350c2c38435a3b20d454b17f8fbbd2a1d8a (patch)
tree080d38a2c80450e956bffb75267deb1a114fed2e /src/libsyntax/ext
parent014620af902c4798ede78462b2d0e3b749fb2fff (diff)
parent18b71a78314505b4dd3816f9662709860aafaf4c (diff)
downloadrust-34aaf350c2c38435a3b20d454b17f8fbbd2a1d8a.tar.gz
rust-34aaf350c2c38435a3b20d454b17f8fbbd2a1d8a.zip
auto merge of #5317 : luqmana/rust/inline-asm, r=graydon
```Rust
#[cfg(target_os = "macos")]
fn helloworld() {
    unsafe {
        asm!(".pushsection __RODATA, __rodata
                  msg: .asciz \"Hello World!\"
              .popsection
              movq msg@GOTPCREL(%rip), %rdi
              call _puts");
    }
}

#[cfg(target_os = "linux")]
fn helloworld() {
    unsafe {
        asm!(".pushsection .rodata
                  msg: .asciz \"Hello World!\"
              .popsection
              movq msg@GOTPCREL(%rip), %rdi
              call puts");
    }
}

fn main() {
    helloworld();
}
```

```
% rustc foo.rs
% ./foo
Hello World!
```
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/asm.rs174
-rw-r--r--src/libsyntax/ext/base.rs2
2 files changed, 176 insertions, 0 deletions
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
new file mode 100644
index 00000000000..8051a67d8fd
--- /dev/null
+++ b/src/libsyntax/ext/asm.rs
@@ -0,0 +1,174 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+
+/*
+ * Inline assembly support.
+ */
+
+use core::prelude::*;
+
+use ast;
+use codemap::span;
+use ext::base;
+use ext::base::*;
+use parse;
+use parse::token;
+
+enum State {
+    Asm,
+    Outputs,
+    Inputs,
+    Clobbers,
+    Options
+}
+
+fn next_state(s: State) -> Option<State> {
+    match s {
+        Asm      => Some(Outputs),
+        Outputs  => Some(Inputs),
+        Inputs   => Some(Clobbers),
+        Clobbers => Some(Options),
+        Options  => None
+    }
+}
+
+pub fn expand_asm(cx: ext_ctxt, sp: span, tts: &[ast::token_tree])
+    -> base::MacResult {
+
+    let p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
+                                       vec::from_slice(tts));
+
+    let mut asm = ~"";
+    let mut outputs = ~[];
+    let mut inputs = ~[];
+    let mut cons = ~"";
+    let mut volatile = false;
+    let mut alignstack = false;
+
+    let mut state = Asm;
+    loop outer: {
+        match state {
+            Asm => {
+                asm = expr_to_str(cx, p.parse_expr(),
+                                ~"inline assembly must be a string literal.");
+            }
+            Outputs => {
+                while *p.token != token::EOF &&
+                      *p.token != token::COLON &&
+                      *p.token != token::MOD_SEP {
+
+                    if outputs.len() != 0 {
+                        p.eat(&token::COMMA);
+                    }
+
+                    let constraint = p.parse_str();
+                    p.expect(&token::LPAREN);
+                    let out = p.parse_expr();
+                    p.expect(&token::RPAREN);
+
+                    outputs.push((constraint, out));
+                }
+            }
+            Inputs => {
+                while *p.token != token::EOF &&
+                      *p.token != token::COLON &&
+                      *p.token != token::MOD_SEP {
+
+                    if inputs.len() != 0 {
+                        p.eat(&token::COMMA);
+                    }
+
+                    let constraint = p.parse_str();
+                    p.expect(&token::LPAREN);
+                    let in = p.parse_expr();
+                    p.expect(&token::RPAREN);
+
+                    inputs.push((constraint, in));
+                }
+            }
+            Clobbers => {
+                let mut clobs = ~[];
+                while *p.token != token::EOF &&
+                      *p.token != token::COLON &&
+                      *p.token != token::MOD_SEP {
+
+                    if clobs.len() != 0 {
+                        p.eat(&token::COMMA);
+                    }
+
+                    let clob = ~"~{" + *p.parse_str() + ~"}";
+                    clobs.push(clob);
+                }
+
+                cons = str::connect(clobs, ",");
+            }
+            Options => {
+                let option = *p.parse_str();
+
+                if option == ~"volatile" {
+                    volatile = true;
+                } else if option == ~"alignstack" {
+                    alignstack = true;
+                }
+
+                if *p.token == token::COMMA {
+                    p.eat(&token::COMMA);
+                }
+            }
+        }
+
+        while *p.token == token::COLON   ||
+              *p.token == token::MOD_SEP ||
+              *p.token == token::EOF {
+            state = if *p.token == token::COLON {
+                p.bump();
+                match next_state(state) {
+                    Some(x) => x,
+                    None    => break outer
+                }
+            } else if *p.token == token::MOD_SEP {
+                p.bump();
+                let s = match next_state(state) {
+                    Some(x) => x,
+                    None    => break outer
+                };
+                match next_state(s) {
+                    Some(x) => x,
+                    None    => break outer
+                }
+            } else if *p.token == token::EOF {
+                break outer;
+            } else {
+               state
+            };
+        }
+    }
+
+    MRExpr(@ast::expr {
+        id: cx.next_id(),
+        callee_id: cx.next_id(),
+        node: ast::expr_inline_asm(@asm, @cons, volatile, alignstack),
+        span: sp
+    })
+}
+
+
+
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
+//
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 23cabc09946..1eae4b84cc9 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -198,6 +198,8 @@ pub fn syntax_expander_table() -> SyntaxEnv {
                                 ext::source_util::expand_mod));
     syntax_expanders.insert(@~"proto",
                             builtin_item_tt(ext::pipes::expand_proto));
+    syntax_expanders.insert(@~"asm",
+                            builtin_normal_tt(ext::asm::expand_asm));
     syntax_expanders.insert(
         @~"trace_macros",
         builtin_normal_tt(ext::trace_macros::expand_trace_macros));