First attempt at global_asm! macro

This commit is contained in:
A.J. Gardner 2017-03-15 21:27:40 -05:00
parent 14481f7210
commit 768e902941
31 changed files with 180 additions and 6 deletions

View File

@ -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",
}
}

View File

@ -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);

View File

@ -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))
}

View File

@ -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(..) => {}

View File

@ -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",

View File

@ -1495,6 +1495,12 @@ pub struct ForeignMod {
pub items: HirVec<ForeignItem>,
}
#[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",

View File

@ -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)?;

View File

@ -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>,

View File

@ -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) => {

View File

@ -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);
}

View File

@ -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(_) |

View File

@ -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(..) |

View File

@ -267,6 +267,7 @@ pub enum EntryKind<'tcx> {
ForeignImmStatic,
ForeignMutStatic,
ForeignMod,
GlobalAsm,
Type,
Enum(ReprOptions),
Field,

View File

@ -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(..) => {

View File

@ -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(..) => {

View File

@ -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
}

View File

@ -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: {:?}",

View File

@ -701,6 +701,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
Def::SelfTy(..) |
Def::Label(..) |
Def::Macro(..) |
Def::GlobalAsm(..) |
Def::Err => None,
}
}

View File

@ -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(..) |

View File

@ -1074,6 +1074,7 @@ fn ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ItemTrait(..) |
ItemMod(..) |
ItemForeignMod(..) |
ItemGlobalAsm(..) |
ItemExternCrate(..) |
ItemUse(..) => {
span_bug!(

View File

@ -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(..) => {}

View File

@ -251,6 +251,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
hir::ItemFn(..) |
hir::ItemMod(..) |
hir::ItemForeignMod(..) |
hir::ItemGlobalAsm(..) |
hir::ItemTy(..) => {}
}
}

View File

@ -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 {

View File

@ -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",

View File

@ -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,

View File

@ -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";

View File

@ -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))
}

View File

@ -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)?;

View File

@ -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) => {

View File

@ -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,
})))
}

View File

@ -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,