about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorLuqman Aden <me@luqman.ca>2013-03-12 00:01:09 -0700
committerLuqman Aden <me@luqman.ca>2013-03-12 01:03:34 -0700
commit5aa734d6a1946e526832bb602e1bb271bf26c0b1 (patch)
treef9c2332f54666a31c4bb7ffa5a2cb1e85e2c895a /src/libsyntax
parent885d0d3d3369bef72590a4d5671c0de83e968dda (diff)
downloadrust-5aa734d6a1946e526832bb602e1bb271bf26c0b1.tar.gz
rust-5aa734d6a1946e526832bb602e1bb271bf26c0b1.zip
Parse operands properly and add a way to indicate volatile asm.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/ext/asm.rs140
-rw-r--r--src/libsyntax/print/pprust.rs8
3 files changed, 137 insertions, 14 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index b7c30360613..dab5de47aa6 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -601,7 +601,8 @@ pub enum expr_ {
     expr_ret(Option<@expr>),
     expr_log(log_level, @expr, @expr),
     
-    expr_inline_asm(@~str /* asm */, @~str /* constraints */),
+    /* asm, clobbers + constraints, volatile */
+    expr_inline_asm(@~str, @~str, bool),
 
     expr_mac(mac),
 
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index bbf42389907..229d1d2a95e 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -20,29 +20,147 @@ 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 args = get_exprs_from_tts(cx, tts);
-    if args.len() == 0 {
-        cx.span_fatal(sp, "ast! takes at least 1 argument.");
+
+    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 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;
+                }
+
+                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 
+            };
+        }
     }
-    let asm =
-        expr_to_str(cx, args[0],
-                    ~"inline assembly must be a string literal.");
-    let cons = if args.len() > 1 {
-        expr_to_str(cx, args[1],
-                    ~"constraints must be a string literal.")
-    } else { ~"" };
 
     MRExpr(@ast::expr {
         id: cx.next_id(),
         callee_id: cx.next_id(),
-        node: ast::expr_inline_asm(@asm, @cons),
+        node: ast::expr_inline_asm(@asm, @cons, volatile),
         span: sp
     })
 }
 
+
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 25c18adb2fb..6b1a72b92ff 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1398,8 +1398,12 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
           }
         }
       }
-      ast::expr_inline_asm(a, c) => {
-        word(s.s, ~"__asm__");
+      ast::expr_inline_asm(a, c, v) => {
+        if v {
+            word(s.s, ~"__volatile__ asm!");
+        } else {
+            word(s.s, ~"asm!");
+        }
         popen(s);
         print_string(s, *a);
         word_space(s, ~",");