]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/asm.rs
libsyntax: Allow selecting intel style asm.
[rust.git] / src / libsyntax / ext / asm.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12
13 /*
14  * Inline assembly support.
15  */
16
17 use core::prelude::*;
18
19 use ast;
20 use codemap::span;
21 use ext::base;
22 use ext::base::*;
23 use parse;
24 use parse::token;
25
26 enum State {
27     Asm,
28     Outputs,
29     Inputs,
30     Clobbers,
31     Options
32 }
33
34 fn next_state(s: State) -> Option<State> {
35     match s {
36         Asm      => Some(Outputs),
37         Outputs  => Some(Inputs),
38         Inputs   => Some(Clobbers),
39         Clobbers => Some(Options),
40         Options  => None
41     }
42 }
43
44 pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
45                -> base::MacResult {
46     let p = parse::new_parser_from_tts(cx.parse_sess(),
47                                        cx.cfg(),
48                                        vec::from_slice(tts));
49
50     let mut asm = ~"";
51     let mut outputs = ~[];
52     let mut inputs = ~[];
53     let mut cons = ~"";
54     let mut volatile = false;
55     let mut alignstack = false;
56     let mut dialect = ast::asm_att;
57
58     let mut state = Asm;
59     loop outer: {
60         match state {
61             Asm => {
62                 asm = expr_to_str(cx, p.parse_expr(),
63                                   ~"inline assembly must be a string literal.");
64             }
65             Outputs => {
66                 while *p.token != token::EOF &&
67                       *p.token != token::COLON &&
68                       *p.token != token::MOD_SEP {
69
70                     if outputs.len() != 0 {
71                         p.eat(&token::COMMA);
72                     }
73
74                     let constraint = p.parse_str();
75                     p.expect(&token::LPAREN);
76                     let out = p.parse_expr();
77                     p.expect(&token::RPAREN);
78
79                     let out = @ast::expr {
80                         id: cx.next_id(),
81                         callee_id: cx.next_id(),
82                         span: out.span,
83                         node: ast::expr_addr_of(ast::m_mutbl, out)
84                     };
85
86                     outputs.push((constraint, out));
87                 }
88             }
89             Inputs => {
90                 while *p.token != token::EOF &&
91                       *p.token != token::COLON &&
92                       *p.token != token::MOD_SEP {
93
94                     if inputs.len() != 0 {
95                         p.eat(&token::COMMA);
96                     }
97
98                     let constraint = p.parse_str();
99                     p.expect(&token::LPAREN);
100                     let in = p.parse_expr();
101                     p.expect(&token::RPAREN);
102
103                     inputs.push((constraint, in));
104                 }
105             }
106             Clobbers => {
107                 let mut clobs = ~[];
108                 while *p.token != token::EOF &&
109                       *p.token != token::COLON &&
110                       *p.token != token::MOD_SEP {
111
112                     if clobs.len() != 0 {
113                         p.eat(&token::COMMA);
114                     }
115
116                     let clob = ~"~{" + *p.parse_str() + ~"}";
117                     clobs.push(clob);
118                 }
119
120                 cons = str::connect(clobs, ",");
121             }
122             Options => {
123                 let option = *p.parse_str();
124
125                 if option == ~"volatile" {
126                     volatile = true;
127                 } else if option == ~"alignstack" {
128                     alignstack = true;
129                 } else if option == ~"intel" {
130                     dialect = ast::asm_intel;
131                 }
132
133                 if *p.token == token::COMMA {
134                     p.eat(&token::COMMA);
135                 }
136             }
137         }
138
139         while *p.token == token::COLON   ||
140               *p.token == token::MOD_SEP ||
141               *p.token == token::EOF {
142             state = if *p.token == token::COLON {
143                 p.bump();
144                 match next_state(state) {
145                     Some(x) => x,
146                     None    => break outer
147                 }
148             } else if *p.token == token::MOD_SEP {
149                 p.bump();
150                 let s = match next_state(state) {
151                     Some(x) => x,
152                     None    => break outer
153                 };
154                 match next_state(s) {
155                     Some(x) => x,
156                     None    => break outer
157                 }
158             } else if *p.token == token::EOF {
159                 break outer;
160             } else {
161                state
162             };
163         }
164     }
165
166     MRExpr(@ast::expr {
167         id: cx.next_id(),
168         callee_id: cx.next_id(),
169         node: ast::expr_inline_asm(ast::inline_asm {
170             asm: @asm,
171             clobbers: @cons,
172             inputs: inputs,
173             outputs: outputs,
174             volatile: volatile,
175             alignstack: alignstack,
176             dialect: dialect
177         }),
178         span: sp
179     })
180 }
181
182
183
184 //
185 // Local Variables:
186 // mode: rust
187 // fill-column: 78;
188 // indent-tabs-mode: nil
189 // c-basic-offset: 4
190 // buffer-file-coding-system: utf-8-unix
191 // End:
192 //