Skip to content

Commit 34aaf35

Browse files
committed
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! ```
2 parents 014620a + 18b71a7 commit 34aaf35

File tree

20 files changed

+269
-11
lines changed

20 files changed

+269
-11
lines changed

src/librustc/lib/llvm.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ pub enum Metadata {
188188
MD_tbaa_struct = 5
189189
}
190190

191+
// Inline Asm Dialect
192+
pub enum AsmDialect {
193+
AD_ATT = 0,
194+
AD_Intel = 1
195+
}
196+
191197
// Opaque pointer types
192198
pub enum Module_opaque {}
193199
pub type ModuleRef = *Module_opaque;
@@ -217,9 +223,9 @@ pub enum SectionIterator_opaque {}
217223
pub type SectionIteratorRef = *SectionIterator_opaque;
218224

219225
pub mod llvm {
220-
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, Bool, BuilderRef};
221-
use super::{ContextRef, MemoryBufferRef, ModuleRef, ObjectFileRef};
222-
use super::{Opcode, PassManagerRef, PassManagerBuilderRef};
226+
use super::{AsmDialect, AtomicBinOp, AtomicOrdering, BasicBlockRef};
227+
use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
228+
use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
223229
use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
224230
use super::{ValueRef};
225231

@@ -1433,6 +1439,12 @@ pub mod llvm {
14331439

14341440
/** Enables LLVM debug output. */
14351441
pub unsafe fn LLVMSetDebug(Enabled: c_int);
1442+
1443+
/** Prepares inline assembly. */
1444+
pub unsafe fn LLVMInlineAsm(Ty: TypeRef, AsmString: *c_char,
1445+
Constraints: *c_char, SideEffects: Bool,
1446+
AlignStack: Bool, Dialect: AsmDialect)
1447+
-> ValueRef;
14361448
}
14371449
}
14381450

src/librustc/middle/liveness.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,8 @@ fn visit_expr(expr: @expr, &&self: @mut IrMaps, vt: vt<@mut IrMaps>) {
620620
expr_do_body(*) | expr_cast(*) | expr_unary(*) | expr_break(_) |
621621
expr_again(_) | expr_lit(_) | expr_ret(*) | expr_block(*) |
622622
expr_assign(*) | expr_swap(*) | expr_assign_op(*) | expr_mac(*) |
623-
expr_struct(*) | expr_repeat(*) | expr_paren(*) => {
623+
expr_struct(*) | expr_repeat(*) | expr_paren(*) |
624+
expr_inline_asm(*) => {
624625
visit::visit_expr(expr, self, vt);
625626
}
626627
}
@@ -1345,6 +1346,7 @@ pub impl Liveness {
13451346
self.propagate_through_expr(e, succ)
13461347
}
13471348
1349+
expr_inline_asm(*) |
13481350
expr_lit(*) => {
13491351
succ
13501352
}
@@ -1618,7 +1620,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
16181620
expr_cast(*) | expr_unary(*) | expr_ret(*) | expr_break(*) |
16191621
expr_again(*) | expr_lit(_) | expr_block(*) | expr_swap(*) |
16201622
expr_mac(*) | expr_addr_of(*) | expr_struct(*) | expr_repeat(*) |
1621-
expr_paren(*) => {
1623+
expr_paren(*) | expr_inline_asm(*) => {
16221624
visit::visit_expr(expr, self, vt);
16231625
}
16241626
}

src/librustc/middle/mem_categorization.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ pub impl mem_categorization_ctxt {
447447
ast::expr_while(*) | ast::expr_block(*) | ast::expr_loop(*) |
448448
ast::expr_match(*) | ast::expr_lit(*) | ast::expr_break(*) |
449449
ast::expr_mac(*) | ast::expr_again(*) | ast::expr_struct(*) |
450-
ast::expr_repeat(*) => {
450+
ast::expr_repeat(*) | ast::expr_inline_asm(*) => {
451451
return self.cat_rvalue(expr, expr_ty);
452452
}
453453
}

src/librustc/middle/moves.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,8 @@ pub impl VisitContext {
560560

561561
expr_break(*) |
562562
expr_again(*) |
563-
expr_lit(*) => {}
563+
expr_lit(*) |
564+
expr_inline_asm(*) => {}
564565

565566
expr_loop(ref blk, _) => {
566567
self.consume_block(blk, visitor);

src/librustc/middle/trans/build.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use lib::llvm::llvm;
12-
use lib::llvm::{CallConv, TypeKind, AtomicBinOp, AtomicOrdering};
12+
use lib::llvm::{CallConv, TypeKind, AtomicBinOp, AtomicOrdering, AsmDialect};
1313
use lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False};
1414
use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
1515
use lib;
@@ -18,7 +18,7 @@ use syntax::codemap::span;
1818

1919
use core::prelude::*;
2020
use core::cast;
21-
use core::libc::{c_uint, c_int, c_ulonglong};
21+
use core::libc::{c_uint, c_int, c_ulonglong, c_char};
2222
use core::libc;
2323
use core::option::Some;
2424
use core::ptr;
@@ -872,6 +872,25 @@ pub fn add_comment(bcx: block, text: &str) {
872872
}
873873
}
874874
875+
pub fn InlineAsmCall(cx: block, asm: *c_char, cons: *c_char,
876+
volatile: bool, alignstack: bool,
877+
dia: AsmDialect) -> ValueRef {
878+
unsafe {
879+
count_insn(cx, "inlineasm");
880+
881+
let volatile = if volatile { lib::llvm::True }
882+
else { lib::llvm::False };
883+
let alignstack = if alignstack { lib::llvm::True }
884+
else { lib::llvm::False };
885+
886+
let llfty = T_fn(~[], T_void());
887+
let v = llvm::LLVMInlineAsm(llfty, asm, cons, volatile,
888+
alignstack, dia);
889+
890+
Call(cx, v, ~[])
891+
}
892+
}
893+
875894
pub fn Call(cx: block, Fn: ValueRef, Args: &[ValueRef]) -> ValueRef {
876895
if cx.unreachable { return _UndefReturn(cx, Fn); }
877896
unsafe {

src/librustc/middle/trans/expr.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,17 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
691691
ast::expr_assign_op(op, dst, src) => {
692692
return trans_assign_op(bcx, expr, op, dst, src);
693693
}
694+
ast::expr_inline_asm(asm, cons, volatile, alignstack) => {
695+
// XXX: cons doesn't actual contain ALL the stuff we should
696+
// be passing since the constraints for in/outputs aren't included
697+
do str::as_c_str(*asm) |a| {
698+
do str::as_c_str(*cons) |c| {
699+
InlineAsmCall(bcx, a, c, volatile, alignstack,
700+
lib::llvm::AD_ATT);
701+
}
702+
}
703+
return bcx;
704+
}
694705
_ => {
695706
bcx.tcx().sess.span_bug(
696707
expr.span,

src/librustc/middle/trans/type_use.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
353353
expr_match(*) | expr_block(_) | expr_if(*) | expr_while(*) |
354354
expr_break(_) | expr_again(_) | expr_unary(_, _) | expr_lit(_) |
355355
expr_mac(_) | expr_addr_of(_, _) | expr_ret(_) | expr_loop(_, _) |
356-
expr_loop_body(_) | expr_do_body(_) => ()
356+
expr_loop_body(_) | expr_do_body(_) | expr_inline_asm(*) => ()
357357
}
358358
}
359359

src/librustc/middle/ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3076,6 +3076,7 @@ pub fn expr_kind(tcx: ctxt,
30763076
ast::expr_block(*) |
30773077
ast::expr_copy(*) |
30783078
ast::expr_repeat(*) |
3079+
ast::expr_inline_asm(*) |
30793080
ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
30803081
ast::expr_vstore(_, ast::expr_vstore_slice) |
30813082
ast::expr_vstore(_, ast::expr_vstore_mut_slice) |

src/librustc/middle/typeck/check/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
23032303
let region_lb = ty::re_scope(expr.id);
23042304
instantiate_path(fcx, pth, tpt, expr.span, expr.id, region_lb);
23052305
}
2306+
ast::expr_inline_asm(*) => {
2307+
fcx.require_unsafe(expr.span, ~"use of inline assembly");
2308+
fcx.write_nil(id);
2309+
}
23062310
ast::expr_mac(_) => tcx.sess.bug(~"unexpanded macro"),
23072311
ast::expr_break(_) => { fcx.write_bot(id); bot = true; }
23082312
ast::expr_again(_) => { fcx.write_bot(id); bot = true; }

src/librustc/middle/typeck/check/regionck.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ pub mod guarantor {
682682

683683
// All of these expressions are rvalues and hence their
684684
// value is not guaranteed by a region pointer.
685+
ast::expr_inline_asm(*) |
685686
ast::expr_mac(*) |
686687
ast::expr_lit(_) |
687688
ast::expr_unary(*) |

src/libsyntax/ast.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,9 @@ pub enum expr_ {
601601
expr_ret(Option<@expr>),
602602
expr_log(log_level, @expr, @expr),
603603
604+
/* asm, clobbers + constraints, volatile, align stack */
605+
expr_inline_asm(@~str, @~str, bool, bool),
606+
604607
expr_mac(mac),
605608
606609
// A struct literal expression.

src/libsyntax/ext/asm.rs

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
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+
47+
let p = parse::new_parser_from_tts(cx.parse_sess(), 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+
57+
let mut state = Asm;
58+
loop outer: {
59+
match state {
60+
Asm => {
61+
asm = expr_to_str(cx, p.parse_expr(),
62+
~"inline assembly must be a string literal.");
63+
}
64+
Outputs => {
65+
while *p.token != token::EOF &&
66+
*p.token != token::COLON &&
67+
*p.token != token::MOD_SEP {
68+
69+
if outputs.len() != 0 {
70+
p.eat(&token::COMMA);
71+
}
72+
73+
let constraint = p.parse_str();
74+
p.expect(&token::LPAREN);
75+
let out = p.parse_expr();
76+
p.expect(&token::RPAREN);
77+
78+
outputs.push((constraint, out));
79+
}
80+
}
81+
Inputs => {
82+
while *p.token != token::EOF &&
83+
*p.token != token::COLON &&
84+
*p.token != token::MOD_SEP {
85+
86+
if inputs.len() != 0 {
87+
p.eat(&token::COMMA);
88+
}
89+
90+
let constraint = p.parse_str();
91+
p.expect(&token::LPAREN);
92+
let in = p.parse_expr();
93+
p.expect(&token::RPAREN);
94+
95+
inputs.push((constraint, in));
96+
}
97+
}
98+
Clobbers => {
99+
let mut clobs = ~[];
100+
while *p.token != token::EOF &&
101+
*p.token != token::COLON &&
102+
*p.token != token::MOD_SEP {
103+
104+
if clobs.len() != 0 {
105+
p.eat(&token::COMMA);
106+
}
107+
108+
let clob = ~"~{" + *p.parse_str() + ~"}";
109+
clobs.push(clob);
110+
}
111+
112+
cons = str::connect(clobs, ",");
113+
}
114+
Options => {
115+
let option = *p.parse_str();
116+
117+
if option == ~"volatile" {
118+
volatile = true;
119+
} else if option == ~"alignstack" {
120+
alignstack = true;
121+
}
122+
123+
if *p.token == token::COMMA {
124+
p.eat(&token::COMMA);
125+
}
126+
}
127+
}
128+
129+
while *p.token == token::COLON ||
130+
*p.token == token::MOD_SEP ||
131+
*p.token == token::EOF {
132+
state = if *p.token == token::COLON {
133+
p.bump();
134+
match next_state(state) {
135+
Some(x) => x,
136+
None => break outer
137+
}
138+
} else if *p.token == token::MOD_SEP {
139+
p.bump();
140+
let s = match next_state(state) {
141+
Some(x) => x,
142+
None => break outer
143+
};
144+
match next_state(s) {
145+
Some(x) => x,
146+
None => break outer
147+
}
148+
} else if *p.token == token::EOF {
149+
break outer;
150+
} else {
151+
state
152+
};
153+
}
154+
}
155+
156+
MRExpr(@ast::expr {
157+
id: cx.next_id(),
158+
callee_id: cx.next_id(),
159+
node: ast::expr_inline_asm(@asm, @cons, volatile, alignstack),
160+
span: sp
161+
})
162+
}
163+
164+
165+
166+
//
167+
// Local Variables:
168+
// mode: rust
169+
// fill-column: 78;
170+
// indent-tabs-mode: nil
171+
// c-basic-offset: 4
172+
// buffer-file-coding-system: utf-8-unix
173+
// End:
174+
//

src/libsyntax/ext/base.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ pub fn syntax_expander_table() -> SyntaxEnv {
198198
ext::source_util::expand_mod));
199199
syntax_expanders.insert(@~"proto",
200200
builtin_item_tt(ext::pipes::expand_proto));
201+
syntax_expanders.insert(@~"asm",
202+
builtin_normal_tt(ext::asm::expand_asm));
201203
syntax_expanders.insert(
202204
@~"trace_macros",
203205
builtin_normal_tt(ext::trace_macros::expand_trace_macros));

src/libsyntax/fold.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
560560
fld.fold_expr(e)
561561
)
562562
}
563+
expr_inline_asm(*) => copy *e,
563564
expr_mac(ref mac) => expr_mac(fold_mac((*mac))),
564565
expr_struct(path, ref fields, maybe_expr) => {
565566
expr_struct(

src/libsyntax/parse/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use ast::{expr_field, expr_fn_block, expr_if, expr_index};
2727
use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
2828
use ast::{expr_method_call, expr_paren, expr_path, expr_repeat};
2929
use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary};
30-
use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
30+
use ast::{expr_vec, expr_vstore, expr_vstore_mut_box, expr_inline_asm};
3131
use ast::{expr_vstore_fixed, expr_vstore_slice, expr_vstore_box};
3232
use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
3333
use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many};

0 commit comments

Comments
 (0)