about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorA.J. Gardner <aaron.j.gardner@gmail.com>2017-03-15 21:27:40 -0500
committerA.J. Gardner <aaron.j.gardner@gmail.com>2017-04-12 19:12:49 -0500
commit768e9029413c6fa3857cf8ba7d943bb297a58ee3 (patch)
treeff3ec89e044e014c86605a423a2447031d30ade0 /src
parent14481f72102ba2abb5f314d5537fee90352981c5 (diff)
downloadrust-768e9029413c6fa3857cf8ba7d943bb297a58ee3.tar.gz
rust-768e9029413c6fa3857cf8ba7d943bb297a58ee3.zip
First attempt at global_asm! macro
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/def.rs6
-rw-r--r--src/librustc/hir/intravisit.rs1
-rw-r--r--src/librustc/hir/lowering.rs8
-rw-r--r--src/librustc/hir/map/def_collector.rs1
-rw-r--r--src/librustc/hir/map/mod.rs1
-rw-r--r--src/librustc/hir/mod.rs9
-rw-r--r--src/librustc/hir/print.rs5
-rw-r--r--src/librustc/ich/impls_hir.rs13
-rw-r--r--src/librustc/middle/reachable.rs3
-rw-r--r--src/librustc/middle/resolve_lifetime.rs3
-rw-r--r--src/librustc_metadata/decoder.rs1
-rw-r--r--src/librustc_metadata/encoder.rs2
-rw-r--r--src/librustc_metadata/schema.rs1
-rw-r--r--src/librustc_privacy/lib.rs13
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs2
-rw-r--r--src/librustc_resolve/lib.rs2
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs1
-rw-r--r--src/librustc_save_analysis/lib.rs1
-rw-r--r--src/librustc_trans/collector.rs1
-rw-r--r--src/librustc_typeck/collect.rs1
-rw-r--r--src/librustc_typeck/variance/constraints.rs1
-rw-r--r--src/librustc_typeck/variance/terms.rs1
-rw-r--r--src/librustdoc/visit_ast.rs1
-rw-r--r--src/libsyntax/ast.rs12
-rw-r--r--src/libsyntax/ext/expand.rs1
-rw-r--r--src/libsyntax/feature_gate.rs6
-rw-r--r--src/libsyntax/fold.rs10
-rw-r--r--src/libsyntax/print/pprust.rs5
-rw-r--r--src/libsyntax/visit.rs6
-rw-r--r--src/libsyntax_ext/global_asm.rs66
-rw-r--r--src/libsyntax_ext/lib.rs2
31 files changed, 180 insertions, 6 deletions
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 7bab4a8d725..771031db0c0 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -57,6 +57,8 @@ pub enum Def {
     // Macro namespace
     Macro(DefId, MacroKind),
 
+    GlobalAsm(DefId),
+
     // Both namespaces
     Err,
 }
@@ -144,7 +146,8 @@ impl Def {
             Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
-            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) => {
+            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) |
+            Def::GlobalAsm(id) => {
                 id
             }
 
@@ -185,6 +188,7 @@ impl Def {
             Def::Label(..) => "label",
             Def::SelfTy(..) => "self type",
             Def::Macro(..) => "macro",
+            Def::GlobalAsm(..) => "global asm",
             Def::Err => "unresolved item",
         }
     }
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 2c8b145f126..9615ed4af06 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -474,6 +474,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
+        ItemGlobalAsm(_) => {}
         ItemTy(ref typ, ref type_parameters) => {
             visitor.visit_id(item.id);
             visitor.visit_ty(typ);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 30fec50d4eb..c86aaa7bf67 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -646,6 +646,13 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
+    fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
+        P(hir::GlobalAsm {
+            asm: ga.asm,
+            ctxt: ga.ctxt,
+        })
+    }
+
     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
         Spanned {
             node: hir::Variant_ {
@@ -1288,6 +1295,7 @@ impl<'a> LoweringContext<'a> {
             }
             ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
+            ItemKind::GlobalAsm(ref ga) => hir::ItemGlobalAsm(self.lower_global_asm(ga)),
             ItemKind::Ty(ref t, ref generics) => {
                 hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
             }
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index c1417f718b2..7ff5152c71a 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -109,6 +109,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                 DefPathData::ValueNs(i.ident.name.as_str()),
             ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
+            ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(ref view_path) => {
                 match view_path.node {
                     ViewPathGlob(..) => {}
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index cfafec00ae2..48b8a819fff 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -1077,6 +1077,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemFn(..) => "fn",
                 ItemMod(..) => "mod",
                 ItemForeignMod(..) => "foreign mod",
+                ItemGlobalAsm(..) => "global asm",
                 ItemTy(..) => "ty",
                 ItemEnum(..) => "enum",
                 ItemStruct(..) => "struct",
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 0da405d1821..562b5884440 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1496,6 +1496,12 @@ pub struct ForeignMod {
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct GlobalAsm {
+    pub asm: Symbol,
+    pub ctxt: SyntaxContext,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct EnumDef {
     pub variants: HirVec<Variant>,
 }
@@ -1686,6 +1692,8 @@ pub enum Item_ {
     ItemMod(Mod),
     /// An external module
     ItemForeignMod(ForeignMod),
+    /// Module-level inline assembly (from global_asm!)
+    ItemGlobalAsm(P<GlobalAsm>),
     /// A type alias, e.g. `type Foo = Bar<u8>`
     ItemTy(P<Ty>, Generics),
     /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
@@ -1720,6 +1728,7 @@ impl Item_ {
             ItemFn(..) => "function",
             ItemMod(..) => "module",
             ItemForeignMod(..) => "foreign module",
+            ItemGlobalAsm(..) => "global asm",
             ItemTy(..) => "type alias",
             ItemEnum(..) => "enum",
             ItemStruct(..) => "struct",
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 4a5a35aa82c..5144f75b1a3 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -633,6 +633,11 @@ impl<'a> State<'a> {
                 self.print_foreign_mod(nmod, &item.attrs)?;
                 self.bclose(item.span)?;
             }
+            hir::ItemGlobalAsm(ref ga) => {
+                self.head(&visibility_qualified(&item.vis, "global asm"))?;
+                word(&mut self.s, &ga.asm.as_str())?;
+                self.end()?
+            }
             hir::ItemTy(ref ty, ref params) => {
                 self.ibox(indent_unit)?;
                 self.ibox(0)?;
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 9cf8a0693d3..5b8dc96f013 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -1014,6 +1014,19 @@ impl_stable_hash_for!(struct hir::InlineAsmOutput {
     is_indirect
 });
 
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::GlobalAsm {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::GlobalAsm {
+            asm,
+            ctxt: _
+        } = *self;
+
+        asm.hash_stable(hcx, hasher);
+    }
+}
+
 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::InlineAsm {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index e5dd48534a6..63455f94ced 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -267,7 +267,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                     hir::ItemMod(..) | hir::ItemForeignMod(..) |
                     hir::ItemImpl(..) | hir::ItemTrait(..) |
                     hir::ItemStruct(..) | hir::ItemEnum(..) |
-                    hir::ItemUnion(..) | hir::ItemDefaultImpl(..) => {}
+                    hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
+                    hir::ItemGlobalAsm(..) => {}
                 }
             }
             hir_map::NodeTraitItem(trait_method) => {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 8037570d24a..b9938a04047 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -314,7 +314,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             hir::ItemUse(..) |
             hir::ItemMod(..) |
             hir::ItemDefaultImpl(..) |
-            hir::ItemForeignMod(..) => {
+            hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) => {
                 // These sorts of items have no lifetime parameters at all.
                 intravisit::walk_item(self, item);
             }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index cdbecb3ae2e..3498be9dfdf 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -429,6 +429,7 @@ impl<'tcx> EntryKind<'tcx> {
             EntryKind::Trait(_) => Def::Trait(did),
             EntryKind::Enum(..) => Def::Enum(did),
             EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
+            EntryKind::GlobalAsm => Def::GlobalAsm(did),
 
             EntryKind::ForeignMod |
             EntryKind::Impl(_) |
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index ffe68094c6a..50ebf6737a8 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -677,6 +677,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
                 return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
             }
             hir::ItemForeignMod(_) => EntryKind::ForeignMod,
+            hir::ItemGlobalAsm(..) => EntryKind::GlobalAsm,
             hir::ItemTy(..) => EntryKind::Type,
             hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
             hir::ItemStruct(ref struct_def, _) => {
@@ -917,6 +918,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
             hir::ItemFn(..) |
             hir::ItemMod(..) |
             hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) |
             hir::ItemExternCrate(..) |
             hir::ItemUse(..) |
             hir::ItemDefaultImpl(..) |
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 53d6a9ec10d..ae20dd1a554 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -267,6 +267,7 @@ pub enum EntryKind<'tcx> {
     ForeignImmStatic,
     ForeignMutStatic,
     ForeignMod,
+    GlobalAsm,
     Type,
     Enum(ReprOptions),
     Field,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 300848fe8f2..92f7e48b6be 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -160,7 +160,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
                 self.prev_level
             }
             // Other `pub` items inherit levels from parents
-            _ => {
+            hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) |
+            hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
+            hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
+            hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
                 if item.vis == hir::Public { self.prev_level } else { None }
             }
         };
@@ -212,7 +215,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
                     }
                 }
             }
-            _ => {}
+            hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
+            hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
+            hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemDefaultImpl(..) => {}
         }
 
         // Mark all items in interfaces of reachable items as reachable
@@ -225,6 +230,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             hir::ItemUse(..) => {}
             // The interface is empty
             hir::ItemDefaultImpl(..) => {}
+            // The interface is empty
+            hir::ItemGlobalAsm(..) => {}
             // Visit everything
             hir::ItemConst(..) | hir::ItemStatic(..) |
             hir::ItemFn(..) | hir::ItemTy(..) => {
@@ -1092,6 +1099,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             hir::ItemMod(..) => {}
             // Checked in resolve
             hir::ItemUse(..) => {}
+            // No subitems
+            hir::ItemGlobalAsm(..) => {}
             // Subitems of these items have inherited publicity
             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
             hir::ItemTy(..) => {
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index a15431afc16..80f853778c7 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -268,6 +268,8 @@ impl<'a> Resolver<'a> {
                 self.define(parent, ident, TypeNS, imported_binding);
             }
 
+            ItemKind::GlobalAsm(..) => {}
+
             ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
 
             ItemKind::Mod(..) => {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c94f63329d1..6ba214f20f9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1709,7 +1709,7 @@ impl<'a> Resolver<'a> {
                 }
             }
 
-            ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) => {
+            ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_)=> {
                 // do nothing, these are just around to be encoded
             }
 
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 3fd0ce45e36..3e8f7e11b6b 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -341,6 +341,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
             Def::AssociatedTy(..) |
             Def::AssociatedConst(..) |
             Def::PrimTy(_) |
+            Def::GlobalAsm(_) |
             Def::Err => {
                span_bug!(span,
                          "process_def_kind for unexpected item: {:?}",
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 44615071a56..d822f7bea3a 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -701,6 +701,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Def::SelfTy(..) |
             Def::Label(..) |
             Def::Macro(..) |
+            Def::GlobalAsm(..) |
             Def::Err => None,
         }
     }
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 500802a4135..479c5b5a1d9 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -811,6 +811,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
             hir::ItemExternCrate(..) |
             hir::ItemUse(..)         |
             hir::ItemForeignMod(..)  |
+            hir::ItemGlobalAsm(..)   |
             hir::ItemTy(..)          |
             hir::ItemDefaultImpl(..) |
             hir::ItemTrait(..)       |
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 77ab076eba3..a7f9b66f659 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1074,6 +1074,7 @@ fn ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemTrait(..) |
                 ItemMod(..) |
                 ItemForeignMod(..) |
+                ItemGlobalAsm(..) |
                 ItemExternCrate(..) |
                 ItemUse(..) => {
                     span_bug!(
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index f0f543fa6f2..1bde1eea37c 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -113,6 +113,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
             hir::ItemFn(..) |
             hir::ItemMod(..) |
             hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) |
             hir::ItemTy(..) |
             hir::ItemImpl(..) |
             hir::ItemDefaultImpl(..) => {}
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 36352f50e44..890414e317c 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -251,6 +251,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
             hir::ItemFn(..) |
             hir::ItemMod(..) |
             hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) |
             hir::ItemTy(..) => {}
         }
     }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index c89ec5bbe15..4252f2981ed 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -373,6 +373,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             }
             // If we're inlining, skip private items.
             _ if self.inlining && item.vis != hir::Public => {}
+            hir::ItemGlobalAsm(..) => {}
             hir::ItemExternCrate(ref p) => {
                 let cstore = &self.cx.sess().cstore;
                 om.extern_crates.push(ExternCrate {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index c6a3e8a2ded..131adfe47af 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1585,6 +1585,15 @@ pub struct ForeignMod {
     pub items: Vec<ForeignItem>,
 }
 
+/// Global inline assembly
+///
+/// aka module-level assembly or file-scoped assembly
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub struct GlobalAsm {
+    pub asm: Symbol,
+    pub ctxt: SyntaxContext,
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct EnumDef {
     pub variants: Vec<Variant>,
@@ -1812,6 +1821,8 @@ pub enum ItemKind {
     ///
     /// E.g. `extern {}` or `extern "C" {}`
     ForeignMod(ForeignMod),
+    /// Module-level inline assembly (from `global_asm!()`)
+    GlobalAsm(P<GlobalAsm>),
     /// A type alias (`type` or `pub type`).
     ///
     /// E.g. `type Foo = Bar<u8>;`
@@ -1864,6 +1875,7 @@ impl ItemKind {
             ItemKind::Fn(..) => "function",
             ItemKind::Mod(..) => "module",
             ItemKind::ForeignMod(..) => "foreign module",
+            ItemKind::GlobalAsm(..) => "global asm",
             ItemKind::Ty(..) => "type alias",
             ItemKind::Enum(..) => "enum",
             ItemKind::Struct(..) => "struct",
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1b3352f73ad..48bfc050223 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1039,6 +1039,7 @@ impl<'feat> ExpansionConfig<'feat> {
     feature_tests! {
         fn enable_quotes = quote,
         fn enable_asm = asm,
+        fn enable_global_asm = global_asm,
         fn enable_log_syntax = log_syntax,
         fn enable_concat_idents = concat_idents,
         fn enable_trace_macros = trace_macros,
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 08762ccf04b..70e4f7a42b6 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -346,6 +346,9 @@ declare_features! (
 
     // Hack to document `-Z linker-flavor` in The Unstable Book
     (active, linker_flavor, "1.18.0", Some(41142)),
+
+    // Allows module-level inline assembly by way of global_asm!()
+    (active, global_asm, "1.18.0", Some(35119)),
 );
 
 declare_features! (
@@ -982,6 +985,9 @@ pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
 pub const EXPLAIN_ASM: &'static str =
     "inline assembly is not stable enough for use and is subject to change";
 
+pub const EXPLAIN_GLOBAL_ASM: &'static str =
+    "module-level inline assembly is experimental and subject to change";
+
 pub const EXPLAIN_LOG_SYNTAX: &'static str =
     "`log_syntax!` is not stable enough for use and is subject to change";
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 92e25b00e0a..a6ab8e10d9f 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -140,6 +140,10 @@ pub trait Folder : Sized {
         noop_fold_foreign_mod(nm, self)
     }
 
+    fn fold_global_asm(&mut self, ga: P<GlobalAsm>) -> P<GlobalAsm> {
+        noop_fold_global_asm(ga, self)
+    }
+
     fn fold_variant(&mut self, v: Variant) -> Variant {
         noop_fold_variant(v, self)
     }
@@ -412,6 +416,11 @@ pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
     }
 }
 
+pub fn noop_fold_global_asm<T: Folder>(ga: P<GlobalAsm>,
+                                       _: &mut T) -> P<GlobalAsm> {
+    ga
+}
+
 pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
     Spanned {
         node: Variant_ {
@@ -867,6 +876,7 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
         }
         ItemKind::Mod(m) => ItemKind::Mod(folder.fold_mod(m)),
         ItemKind::ForeignMod(nm) => ItemKind::ForeignMod(folder.fold_foreign_mod(nm)),
+        ItemKind::GlobalAsm(ga) => ItemKind::GlobalAsm(folder.fold_global_asm(ga)),
         ItemKind::Ty(t, generics) => {
             ItemKind::Ty(folder.fold_ty(t), folder.fold_generics(generics))
         }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index e7feff2b79f..433ba3d3693 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1267,6 +1267,11 @@ impl<'a> State<'a> {
                 self.print_foreign_mod(nmod, &item.attrs)?;
                 self.bclose(item.span)?;
             }
+            ast::ItemKind::GlobalAsm(ref ga) => {
+                self.head(&visibility_qualified(&item.vis, "global_asm!"))?;
+                word(&mut self.s, &ga.asm.as_str())?;
+                self.end()?;
+            }
             ast::ItemKind::Ty(ref ty, ref params) => {
                 self.ibox(INDENT_UNIT)?;
                 self.ibox(0)?;
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index b5e9a1892ac..bae1c56db00 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -58,6 +58,7 @@ pub trait Visitor<'ast>: Sized {
     }
     fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
     fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) }
+    fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) }
     fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
     fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
     fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
@@ -253,6 +254,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
         ItemKind::ForeignMod(ref foreign_module) => {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
+        ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
         ItemKind::Ty(ref typ, ref type_parameters) => {
             visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
@@ -464,6 +466,10 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a
     walk_list!(visitor, visit_attribute, &foreign_item.attrs);
 }
 
+pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
+    // Empty!
+}
+
 pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) {
     match *bound {
         TraitTyParamBound(ref typ, ref modifier) => {
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
new file mode 100644
index 00000000000..d322d138f04
--- /dev/null
+++ b/src/libsyntax_ext/global_asm.rs
@@ -0,0 +1,66 @@
+// Copyright 2012-2013 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.
+
+/// Module-level assembly support.
+///
+/// The macro defined here allows you to specify "top-level",
+/// "file-scoped", or "module-level" assembly. These synonyms
+/// all correspond to LLVM's module-level inline assembly instruction.
+///
+/// For example, `global_asm!("some assembly here")` translates to
+/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
+/// therefore apply.
+
+use syntax::ast;
+use syntax::ext::base;
+use syntax::ext::base::*;
+use syntax::codemap;
+use syntax::feature_gate;
+use syntax::ptr::P;
+use syntax::symbol::Symbol;
+use syntax_pos::Span;
+use syntax::tokenstream;
+
+use syntax::util::small_vector::SmallVector;
+
+pub const MACRO: &'static str = "global_asm";
+
+pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
+                              sp: Span,
+                              tts: &[tokenstream::TokenTree]) -> Box<base::MacResult + 'cx> {
+    if !cx.ecfg.enable_global_asm() {
+        feature_gate::emit_feature_err(&cx.parse_sess,
+                                       MACRO,
+                                       sp,
+                                       feature_gate::GateIssue::Language,
+                                       feature_gate::EXPLAIN_GLOBAL_ASM);
+        return DummyResult::any(sp);
+    }
+
+    let mut p = cx.new_parser_from_tts(tts);
+    let (asm, _) = match expr_to_string(cx,
+                                        panictry!(p.parse_expr()),
+                                        "inline assembly must be a string literal") {
+        Some((s, st)) => (s, st),
+        None => return DummyResult::any(sp),
+    };
+
+    MacEager::items(SmallVector::one(P(ast::Item {
+        ident: ast::Ident::with_empty_ctxt(Symbol::intern("")),
+        attrs: Vec::new(),
+        id: ast::DUMMY_NODE_ID,
+        node: ast::ItemKind::GlobalAsm(P(ast::GlobalAsm {
+            asm: asm,
+            ctxt: cx.backtrace(),
+        })),
+        vis: ast::Visibility::Inherited,
+        span: sp,
+    })))
+}
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 1e9b112b6df..e35e79df585 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -38,6 +38,7 @@ mod concat_idents;
 mod env;
 mod format;
 mod format_foreign;
+mod global_asm;
 mod log_syntax;
 mod trace_macros;
 
@@ -99,6 +100,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
         module_path: expand_mod,
 
         asm: asm::expand_asm,
+        global_asm: global_asm::expand_global_asm,
         cfg: cfg::expand_cfg,
         concat: concat::expand_syntax_ext,
         concat_idents: concat_idents::expand_syntax_ext,