about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-03-12 07:51:54 -0700
committerbors <bors@rust-lang.org>2013-03-12 07:51:54 -0700
commit34aaf350c2c38435a3b20d454b17f8fbbd2a1d8a (patch)
tree080d38a2c80450e956bffb75267deb1a114fed2e
parent014620af902c4798ede78462b2d0e3b749fb2fff (diff)
parent18b71a78314505b4dd3816f9662709860aafaf4c (diff)
downloadrust-34aaf350c2c38435a3b20d454b17f8fbbd2a1d8a.tar.gz
rust-34aaf350c2c38435a3b20d454b17f8fbbd2a1d8a.zip
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!
```
-rw-r--r--src/librustc/lib/llvm.rs18
-rw-r--r--src/librustc/middle/liveness.rs6
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/moves.rs3
-rw-r--r--src/librustc/middle/trans/build.rs23
-rw-r--r--src/librustc/middle/trans/expr.rs11
-rw-r--r--src/librustc/middle/trans/type_use.rs2
-rw-r--r--src/librustc/middle/ty.rs1
-rw-r--r--src/librustc/middle/typeck/check/mod.rs4
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs1
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/ext/asm.rs174
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/fold.rs1
-rw-r--r--src/libsyntax/parse/parser.rs2
-rw-r--r--src/libsyntax/print/pprust.rs12
-rw-r--r--src/libsyntax/syntax.rc1
-rw-r--r--src/libsyntax/visit.rs1
-rw-r--r--src/rustllvm/RustWrapper.cpp12
-rw-r--r--src/rustllvm/rustllvm.def.in1
20 files changed, 269 insertions, 11 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 4cb018ebdd1..b0cc18a30a4 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -188,6 +188,12 @@ pub enum Metadata {
     MD_tbaa_struct = 5
 }
 
+// Inline Asm Dialect
+pub enum AsmDialect {
+    AD_ATT   = 0,
+    AD_Intel = 1
+}
+
 // Opaque pointer types
 pub enum Module_opaque {}
 pub type ModuleRef = *Module_opaque;
@@ -217,9 +223,9 @@ pub enum SectionIterator_opaque {}
 pub type SectionIteratorRef = *SectionIterator_opaque;
 
 pub mod llvm {
-    use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, Bool, BuilderRef};
-    use super::{ContextRef, MemoryBufferRef, ModuleRef, ObjectFileRef};
-    use super::{Opcode, PassManagerRef, PassManagerBuilderRef};
+    use super::{AsmDialect, AtomicBinOp, AtomicOrdering, BasicBlockRef};
+    use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
+    use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
     use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
     use super::{ValueRef};
 
@@ -1433,6 +1439,12 @@ pub mod llvm {
 
         /** Enables LLVM debug output. */
         pub unsafe fn LLVMSetDebug(Enabled: c_int);
+
+        /** Prepares inline assembly. */
+        pub unsafe fn LLVMInlineAsm(Ty: TypeRef, AsmString: *c_char,
+                                    Constraints: *c_char, SideEffects: Bool,
+                                    AlignStack: Bool, Dialect: AsmDialect)
+                                 -> ValueRef;
     }
 }
 
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 0c17b371694..d300698da59 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -620,7 +620,8 @@ fn visit_expr(expr: @expr, &&self: @mut IrMaps, vt: vt<@mut IrMaps>) {
       expr_do_body(*) | expr_cast(*) | expr_unary(*) | expr_break(_) |
       expr_again(_) | expr_lit(_) | expr_ret(*) | expr_block(*) |
       expr_assign(*) | expr_swap(*) | expr_assign_op(*) | expr_mac(*) |
-      expr_struct(*) | expr_repeat(*) | expr_paren(*) => {
+      expr_struct(*) | expr_repeat(*) | expr_paren(*) |
+      expr_inline_asm(*) => {
           visit::visit_expr(expr, self, vt);
       }
     }
@@ -1345,6 +1346,7 @@ pub impl Liveness {
             self.propagate_through_expr(e, succ)
           }
 
+          expr_inline_asm(*) |
           expr_lit(*) => {
             succ
           }
@@ -1618,7 +1620,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
       expr_cast(*) | expr_unary(*) | expr_ret(*) | expr_break(*) |
       expr_again(*) | expr_lit(_) | expr_block(*) | expr_swap(*) |
       expr_mac(*) | expr_addr_of(*) | expr_struct(*) | expr_repeat(*) |
-      expr_paren(*) => {
+      expr_paren(*) | expr_inline_asm(*) => {
         visit::visit_expr(expr, self, vt);
       }
     }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 9e0ecb5a218..5881f95f298 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -447,7 +447,7 @@ pub impl mem_categorization_ctxt {
           ast::expr_while(*) | ast::expr_block(*) | ast::expr_loop(*) |
           ast::expr_match(*) | ast::expr_lit(*) | ast::expr_break(*) |
           ast::expr_mac(*) | ast::expr_again(*) | ast::expr_struct(*) |
-          ast::expr_repeat(*) => {
+          ast::expr_repeat(*) | ast::expr_inline_asm(*) => {
             return self.cat_rvalue(expr, expr_ty);
           }
         }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 182697b290f..734f4651f3b 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -560,7 +560,8 @@ pub impl VisitContext {
 
             expr_break(*) |
             expr_again(*) |
-            expr_lit(*) => {}
+            expr_lit(*)   |
+            expr_inline_asm(*) => {}
 
             expr_loop(ref blk, _) => {
                 self.consume_block(blk, visitor);
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index 45104480b4c..50a7669a1be 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use lib::llvm::llvm;
-use lib::llvm::{CallConv, TypeKind, AtomicBinOp, AtomicOrdering};
+use lib::llvm::{CallConv, TypeKind, AtomicBinOp, AtomicOrdering, AsmDialect};
 use lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False};
 use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
 use lib;
@@ -18,7 +18,7 @@ use syntax::codemap::span;
 
 use core::prelude::*;
 use core::cast;
-use core::libc::{c_uint, c_int, c_ulonglong};
+use core::libc::{c_uint, c_int, c_ulonglong, c_char};
 use core::libc;
 use core::option::Some;
 use core::ptr;
@@ -872,6 +872,25 @@ pub fn add_comment(bcx: block, text: &str) {
     }
 }
 
+pub fn InlineAsmCall(cx: block, asm: *c_char, cons: *c_char,
+                     volatile: bool, alignstack: bool,
+                     dia: AsmDialect) -> ValueRef {
+    unsafe {
+        count_insn(cx, "inlineasm");
+
+        let volatile = if volatile { lib::llvm::True }
+                       else        { lib::llvm::False };
+        let alignstack = if alignstack { lib::llvm::True }
+                         else          { lib::llvm::False };
+
+        let llfty = T_fn(~[], T_void());
+        let v = llvm::LLVMInlineAsm(llfty, asm, cons, volatile,
+                                    alignstack, dia);
+
+        Call(cx, v, ~[])
+    }
+}
+
 pub fn Call(cx: block, Fn: ValueRef, Args: &[ValueRef]) -> ValueRef {
     if cx.unreachable { return _UndefReturn(cx, Fn); }
     unsafe {
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index e38b0be7bcc..c163183bfc8 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -691,6 +691,17 @@ 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, volatile, alignstack) => {
+            // 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, volatile, alignstack,
+                                  lib::llvm::AD_ATT);
+                }
+            }
+            return bcx;
+        }
         _ => {
             bcx.tcx().sess.span_bug(
                 expr.span,
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index 710bb5eb346..9a0c330d2d1 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -353,7 +353,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
       expr_match(*) | expr_block(_) | expr_if(*) | expr_while(*) |
       expr_break(_) | expr_again(_) | expr_unary(_, _) | expr_lit(_) |
       expr_mac(_) | expr_addr_of(_, _) | expr_ret(_) | expr_loop(_, _) |
-      expr_loop_body(_) | expr_do_body(_) => ()
+      expr_loop_body(_) | expr_do_body(_) | expr_inline_asm(*) => ()
     }
 }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index b4ef87491a8..6e21439fc35 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -3076,6 +3076,7 @@ pub fn expr_kind(tcx: ctxt,
         ast::expr_block(*) |
         ast::expr_copy(*) |
         ast::expr_repeat(*) |
+        ast::expr_inline_asm(*) |
         ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
         ast::expr_vstore(_, ast::expr_vstore_slice) |
         ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 6617fa3b27c..445cab4ba95 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -2303,6 +2303,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         let region_lb = ty::re_scope(expr.id);
         instantiate_path(fcx, pth, tpt, expr.span, expr.id, region_lb);
       }
+      ast::expr_inline_asm(*) => {
+          fcx.require_unsafe(expr.span, ~"use of inline assembly");
+          fcx.write_nil(id);
+      }
       ast::expr_mac(_) => tcx.sess.bug(~"unexpanded macro"),
       ast::expr_break(_) => { fcx.write_bot(id); bot = true; }
       ast::expr_again(_) => { fcx.write_bot(id); bot = true; }
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 55d027549e3..1dd88e6408b 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -682,6 +682,7 @@ pub mod guarantor {
 
             // All of these expressions are rvalues and hence their
             // value is not guaranteed by a region pointer.
+            ast::expr_inline_asm(*) |
             ast::expr_mac(*) |
             ast::expr_lit(_) |
             ast::expr_unary(*) |
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 27dba9c2b5e..b22018c4c76 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -601,6 +601,9 @@ pub enum expr_ {
     expr_ret(Option<@expr>),
     expr_log(log_level, @expr, @expr),
 
+    /* asm, clobbers + constraints, volatile, align stack */
+    expr_inline_asm(@~str, @~str, bool, bool),
+
     expr_mac(mac),
 
     // A struct literal expression.
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
new file mode 100644
index 00000000000..8051a67d8fd
--- /dev/null
+++ b/src/libsyntax/ext/asm.rs
@@ -0,0 +1,174 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+
+/*
+ * Inline assembly support.
+ */
+
+use core::prelude::*;
+
+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 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 alignstack = 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;
+                } else if option == ~"alignstack" {
+                    alignstack = 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
+            };
+        }
+    }
+
+    MRExpr(@ast::expr {
+        id: cx.next_id(),
+        callee_id: cx.next_id(),
+        node: ast::expr_inline_asm(@asm, @cons, volatile, alignstack),
+        span: sp
+    })
+}
+
+
+
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
+//
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 23cabc09946..1eae4b84cc9 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -198,6 +198,8 @@ pub fn syntax_expander_table() -> SyntaxEnv {
                                 ext::source_util::expand_mod));
     syntax_expanders.insert(@~"proto",
                             builtin_item_tt(ext::pipes::expand_proto));
+    syntax_expanders.insert(@~"asm",
+                            builtin_normal_tt(ext::asm::expand_asm));
     syntax_expanders.insert(
         @~"trace_macros",
         builtin_normal_tt(ext::trace_macros::expand_trace_macros));
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 427760c920f..15097f57b02 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -560,6 +560,7 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
                 fld.fold_expr(e)
             )
         }
+        expr_inline_asm(*) => copy *e,
         expr_mac(ref mac) => expr_mac(fold_mac((*mac))),
         expr_struct(path, ref fields, maybe_expr) => {
             expr_struct(
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 99c1c2cb1fe..51e36d9ec02 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -27,7 +27,7 @@ use ast::{expr_field, expr_fn_block, expr_if, expr_index};
 use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
 use ast::{expr_method_call, expr_paren, expr_path, expr_repeat};
 use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary};
-use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
+use ast::{expr_vec, expr_vstore, expr_vstore_mut_box, expr_inline_asm};
 use ast::{expr_vstore_fixed, expr_vstore_slice, expr_vstore_box};
 use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
 use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many};
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 62f593f15c1..92883123782 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1398,6 +1398,18 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
           }
         }
       }
+      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, ~",");
+        print_string(s, *c);
+        pclose(s);
+      }
       ast::expr_mac(ref m) => print_mac(s, (*m)),
       ast::expr_paren(e) => {
           popen(s);
diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc
index 7f84d6a3010..e13ef976d97 100644
--- a/src/libsyntax/syntax.rc
+++ b/src/libsyntax/syntax.rc
@@ -60,6 +60,7 @@ pub mod print {
 }
 
 pub mod ext {
+    pub mod asm;
     pub mod base;
     pub mod expand;
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index f04894729bd..95ab603f584 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -562,6 +562,7 @@ pub fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
         }
         expr_mac(ref mac) => visit_mac((*mac), e, v),
         expr_paren(x) => (v.visit_expr)(x, e, v),
+        expr_inline_asm(*) => (),
     }
     (v.visit_expr_post)(ex, e, v);
 }
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 3af936d3461..7686dcd4ff4 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -15,6 +15,7 @@
 //
 //===----------------------------------------------------------------------===
 
+#include "llvm/InlineAsm.h"
 #include "llvm/LLVMContext.h"
 #include "llvm/Linker.h"
 #include "llvm/PassManager.h"
@@ -539,3 +540,14 @@ extern "C" void LLVMSetDebug(int Enabled) {
   DebugFlag = Enabled;
 #endif
 }
+
+extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
+                                      char *AsmString,
+                                      char *Constraints,
+                                      LLVMBool HasSideEffects,
+                                      LLVMBool IsAlignStack,
+                                      InlineAsm::AsmDialect Dialect) {
+    return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
+                               Constraints, HasSideEffects,
+                               IsAlignStack, Dialect));
+}
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index ceedf438296..8b1c9d5ec7f 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -583,3 +583,4 @@ LLVMX86MMXTypeInContext
 LLVMConstNamedStruct
 LLVMStructCreateNamed
 LLVMStructSetBody
+LLVMInlineAsm