Parse operands properly and add a way to indicate volatile asm.
This commit is contained in:
parent
885d0d3d33
commit
5aa734d6a1
@ -873,12 +873,12 @@ pub fn add_comment(bcx: block, text: &str) {
|
||||
}
|
||||
|
||||
pub fn InlineAsmCall(cx: block, asm: *c_char, cons: *c_char,
|
||||
dia: AsmDialect) -> ValueRef {
|
||||
volatile: lib::llvm::Bool, dia: AsmDialect) -> ValueRef {
|
||||
unsafe {
|
||||
count_insn(cx, "inlineasm");
|
||||
|
||||
let llfty = T_fn(~[], T_void());
|
||||
let v = llvm::LLVMInlineAsm(llfty, asm, cons, False, False, dia);
|
||||
let v = llvm::LLVMInlineAsm(llfty, asm, cons, volatile, False, dia);
|
||||
|
||||
Call(cx, v, ~[])
|
||||
}
|
||||
|
@ -691,10 +691,14 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
||||
ast::expr_assign_op(op, dst, src) => {
|
||||
return trans_assign_op(bcx, expr, op, dst, src);
|
||||
}
|
||||
ast::expr_inline_asm(asm, cons) => {
|
||||
ast::expr_inline_asm(asm, cons, volatile) => {
|
||||
// XXX: cons doesn't actual contain ALL the stuff we should
|
||||
// be passing since the constraints for in/outputs aren't included
|
||||
do str::as_c_str(*asm) |a| {
|
||||
do str::as_c_str(*cons) |c| {
|
||||
InlineAsmCall(bcx, a, c, lib::llvm::AD_ATT);
|
||||
let v = if volatile { lib::llvm::True }
|
||||
else { lib::llvm::False };
|
||||
InlineAsmCall(bcx, a, c, v, lib::llvm::AD_ATT);
|
||||
}
|
||||
}
|
||||
return bcx;
|
||||
|
@ -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),
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, ~",");
|
||||
|
Loading…
x
Reference in New Issue
Block a user