1 // Copyright 2012-2013 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.
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.
12 * Inline assembly support.
20 use parse::token::InternedString;
31 fn next_state(s: State) -> Option<State> {
34 Outputs => Some(Inputs),
35 Inputs => Some(Clobbers),
36 Clobbers => Some(Options),
41 pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
43 let mut p = parse::new_parser_from_tts(cx.parse_sess(),
47 let mut asm = InternedString::new("");
48 let mut asm_str_style = None;
49 let mut outputs = ~[];
52 let mut volatile = false;
53 let mut alignstack = false;
54 let mut dialect = ast::AsmAtt;
58 // Not using labeled break to get us through one round of bootstrapping.
59 let mut continue_ = true;
63 let (s, style) = match expr_to_str(cx, p.parse_expr(),
64 "inline assembly must be a string literal.") {
65 Some((s, st)) => (s, st),
66 // let compilation continue
67 None => return MacResult::dummy_expr(),
70 asm_str_style = Some(style);
73 while p.token != token::EOF &&
74 p.token != token::COLON &&
75 p.token != token::MOD_SEP {
77 if outputs.len() != 0 {
81 let (constraint, _str_style) = p.parse_str();
83 if constraint.starts_with("+") {
84 cx.span_unimpl(p.last_span,
85 "'+' (read+write) output operand constraint modifier");
86 } else if !constraint.starts_with("=") {
87 cx.span_err(p.last_span, "output operand constraint lacks '='");
90 p.expect(&token::LPAREN);
91 let out = p.parse_expr();
92 p.expect(&token::RPAREN);
94 outputs.push((constraint, out));
98 while p.token != token::EOF &&
99 p.token != token::COLON &&
100 p.token != token::MOD_SEP {
102 if inputs.len() != 0 {
103 p.eat(&token::COMMA);
106 let (constraint, _str_style) = p.parse_str();
108 if constraint.starts_with("=") {
109 cx.span_err(p.last_span, "input operand constraint contains '='");
110 } else if constraint.starts_with("+") {
111 cx.span_err(p.last_span, "input operand constraint contains '+'");
114 p.expect(&token::LPAREN);
115 let input = p.parse_expr();
116 p.expect(&token::RPAREN);
118 inputs.push((constraint, input));
123 while p.token != token::EOF &&
124 p.token != token::COLON &&
125 p.token != token::MOD_SEP {
127 if clobs.len() != 0 {
128 p.eat(&token::COMMA);
131 let (s, _str_style) = p.parse_str();
132 let clob = format!("~\\{{}\\}", s);
136 cons = clobs.connect(",");
139 let (option, _str_style) = p.parse_str();
141 if "volatile" == option {
143 } else if "alignstack" == option {
145 } else if "intel" == option {
146 dialect = ast::AsmIntel;
149 if p.token == token::COMMA {
150 p.eat(&token::COMMA);
155 while p.token == token::COLON ||
156 p.token == token::MOD_SEP ||
157 p.token == token::EOF {
158 state = if p.token == token::COLON {
160 match next_state(state) {
167 } else if p.token == token::MOD_SEP {
169 let s = match next_state(state) {
176 match next_state(s) {
183 } else if p.token == token::EOF {
193 id: ast::DUMMY_NODE_ID,
194 node: ast::ExprInlineAsm(ast::InlineAsm {
195 asm: asm.get().to_managed(),
196 asm_str_style: asm_str_style.unwrap(),
197 clobbers: cons.to_managed(),
201 alignstack: alignstack,