Rollup merge of #40702 - mrhota:global_asm, r=nagisa
Implement global_asm!() (RFC 1548) This is a first attempt. ~~One (potential) problem I haven't solved is how to handle multiple usages of `global_asm!` in a module/crate. It looks like `LLVMSetModuleInlineAsm` overwrites module asm, and `LLVMAppendModuleInlineAsm` is not provided in LLVM C headers 😦~~ I can provide more detail as needed, but honestly, there's not a lot going on here. r? @eddyb CC @Amanieu @jackpot51 Tracking issue: #35119
This commit is contained in:
commit
e6f6b445aa
|
@ -83,6 +83,7 @@
|
||||||
- [future_atomic_orderings](future-atomic-orderings.md)
|
- [future_atomic_orderings](future-atomic-orderings.md)
|
||||||
- [generic_param_attrs](generic-param-attrs.md)
|
- [generic_param_attrs](generic-param-attrs.md)
|
||||||
- [get_type_id](get-type-id.md)
|
- [get_type_id](get-type-id.md)
|
||||||
|
- [global_asm](global_asm.md)
|
||||||
- [heap_api](heap-api.md)
|
- [heap_api](heap-api.md)
|
||||||
- [i128](i128.md)
|
- [i128](i128.md)
|
||||||
- [i128_type](i128-type.md)
|
- [i128_type](i128-type.md)
|
||||||
|
|
|
@ -189,3 +189,5 @@ constraints, etc.
|
||||||
|
|
||||||
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
|
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
|
||||||
|
|
||||||
|
If you need more power and don't mind losing some of the niceties of
|
||||||
|
`asm!`, check out [global_asm](global_asm.html).
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
# `global_asm`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#35119]
|
||||||
|
|
||||||
|
[#35119]: https://github.com/rust-lang/rust/issues/35119
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The `global_asm!` macro allows the programmer to write arbitrary
|
||||||
|
assembly outside the scope of a function body, passing it through
|
||||||
|
`rustc` and `llvm` to the assembler. The macro is a no-frills
|
||||||
|
interface to LLVM's concept of [module-level inline assembly]. That is,
|
||||||
|
all caveats applicable to LLVM's module-level inline assembly apply
|
||||||
|
to `global_asm!`.
|
||||||
|
|
||||||
|
[module-level inline assembly]: http://llvm.org/docs/LangRef.html#module-level-inline-assembly
|
||||||
|
|
||||||
|
`global_asm!` fills a role not currently satisfied by either `asm!`
|
||||||
|
or `#[naked]` functions. The programmer has _all_ features of the
|
||||||
|
assembler at their disposal. The linker will expect to resolve any
|
||||||
|
symbols defined in the inline assembly, modulo any symbols marked as
|
||||||
|
external. It also means syntax for directives and assembly follow the
|
||||||
|
conventions of the assembler in your toolchain.
|
||||||
|
|
||||||
|
A simple usage looks like this:
|
||||||
|
|
||||||
|
```rust,ignore
|
||||||
|
# #![feature(global_asm)]
|
||||||
|
# you also need relevant target_arch cfgs
|
||||||
|
global_asm!(include_str!("something_neato.s"));
|
||||||
|
```
|
||||||
|
|
||||||
|
And a more complicated usage looks like this:
|
||||||
|
|
||||||
|
```rust,ignore
|
||||||
|
# #![feature(global_asm)]
|
||||||
|
# #![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
|
|
||||||
|
pub mod sally {
|
||||||
|
global_asm!(r#"
|
||||||
|
.global foo
|
||||||
|
foo:
|
||||||
|
jmp baz
|
||||||
|
"#);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn baz() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the symbols `foo` and `bar` are global, no matter where
|
||||||
|
// `global_asm!` was used.
|
||||||
|
extern "C" {
|
||||||
|
fn foo();
|
||||||
|
fn bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod harry {
|
||||||
|
global_asm!(r#"
|
||||||
|
.global bar
|
||||||
|
bar:
|
||||||
|
jmp quux
|
||||||
|
"#);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn quux() {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You may use `global_asm!` multiple times, anywhere in your crate, in
|
||||||
|
whatever way suits you. The effect is as if you concatenated all
|
||||||
|
usages and placed the larger, single usage in the crate root.
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
If you don't need quite as much power and flexibility as
|
||||||
|
`global_asm!` provides, and you don't mind restricting your inline
|
||||||
|
assembly to `fn` bodies only, you might try the [asm](asm.html)
|
||||||
|
feature instead.
|
|
@ -57,6 +57,8 @@ pub enum Def {
|
||||||
// Macro namespace
|
// Macro namespace
|
||||||
Macro(DefId, MacroKind),
|
Macro(DefId, MacroKind),
|
||||||
|
|
||||||
|
GlobalAsm(DefId),
|
||||||
|
|
||||||
// Both namespaces
|
// Both namespaces
|
||||||
Err,
|
Err,
|
||||||
}
|
}
|
||||||
|
@ -144,7 +146,8 @@ impl Def {
|
||||||
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
|
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::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
|
||||||
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(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
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +188,7 @@ impl Def {
|
||||||
Def::Label(..) => "label",
|
Def::Label(..) => "label",
|
||||||
Def::SelfTy(..) => "self type",
|
Def::SelfTy(..) => "self type",
|
||||||
Def::Macro(..) => "macro",
|
Def::Macro(..) => "macro",
|
||||||
|
Def::GlobalAsm(..) => "global asm",
|
||||||
Def::Err => "unresolved item",
|
Def::Err => "unresolved item",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -474,6 +474,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||||
visitor.visit_id(item.id);
|
visitor.visit_id(item.id);
|
||||||
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
||||||
}
|
}
|
||||||
|
ItemGlobalAsm(_) => {
|
||||||
|
visitor.visit_id(item.id);
|
||||||
|
}
|
||||||
ItemTy(ref typ, ref type_parameters) => {
|
ItemTy(ref typ, ref type_parameters) => {
|
||||||
visitor.visit_id(item.id);
|
visitor.visit_id(item.id);
|
||||||
visitor.visit_ty(typ);
|
visitor.visit_ty(typ);
|
||||||
|
|
|
@ -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 {
|
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
|
||||||
Spanned {
|
Spanned {
|
||||||
node: hir::Variant_ {
|
node: hir::Variant_ {
|
||||||
|
@ -1288,6 +1295,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
}
|
}
|
||||||
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
|
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
|
||||||
ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
|
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) => {
|
ItemKind::Ty(ref t, ref generics) => {
|
||||||
hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
|
hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
DefPathData::ValueNs(i.ident.name.as_str()),
|
DefPathData::ValueNs(i.ident.name.as_str()),
|
||||||
ItemKind::MacroDef(..) => DefPathData::MacroDef(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::Mac(..) => return self.visit_macro_invoc(i.id, false),
|
||||||
|
ItemKind::GlobalAsm(..) => DefPathData::Misc,
|
||||||
ItemKind::Use(ref view_path) => {
|
ItemKind::Use(ref view_path) => {
|
||||||
match view_path.node {
|
match view_path.node {
|
||||||
ViewPathGlob(..) => {}
|
ViewPathGlob(..) => {}
|
||||||
|
|
|
@ -1077,6 +1077,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
|
||||||
ItemFn(..) => "fn",
|
ItemFn(..) => "fn",
|
||||||
ItemMod(..) => "mod",
|
ItemMod(..) => "mod",
|
||||||
ItemForeignMod(..) => "foreign mod",
|
ItemForeignMod(..) => "foreign mod",
|
||||||
|
ItemGlobalAsm(..) => "global asm",
|
||||||
ItemTy(..) => "ty",
|
ItemTy(..) => "ty",
|
||||||
ItemEnum(..) => "enum",
|
ItemEnum(..) => "enum",
|
||||||
ItemStruct(..) => "struct",
|
ItemStruct(..) => "struct",
|
||||||
|
|
|
@ -1495,6 +1495,12 @@ pub struct ForeignMod {
|
||||||
pub items: HirVec<ForeignItem>,
|
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)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub struct EnumDef {
|
pub struct EnumDef {
|
||||||
pub variants: HirVec<Variant>,
|
pub variants: HirVec<Variant>,
|
||||||
|
@ -1686,6 +1692,8 @@ pub enum Item_ {
|
||||||
ItemMod(Mod),
|
ItemMod(Mod),
|
||||||
/// An external module
|
/// An external module
|
||||||
ItemForeignMod(ForeignMod),
|
ItemForeignMod(ForeignMod),
|
||||||
|
/// Module-level inline assembly (from global_asm!)
|
||||||
|
ItemGlobalAsm(P<GlobalAsm>),
|
||||||
/// A type alias, e.g. `type Foo = Bar<u8>`
|
/// A type alias, e.g. `type Foo = Bar<u8>`
|
||||||
ItemTy(P<Ty>, Generics),
|
ItemTy(P<Ty>, Generics),
|
||||||
/// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
|
/// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
|
||||||
|
@ -1720,6 +1728,7 @@ impl Item_ {
|
||||||
ItemFn(..) => "function",
|
ItemFn(..) => "function",
|
||||||
ItemMod(..) => "module",
|
ItemMod(..) => "module",
|
||||||
ItemForeignMod(..) => "foreign module",
|
ItemForeignMod(..) => "foreign module",
|
||||||
|
ItemGlobalAsm(..) => "global asm",
|
||||||
ItemTy(..) => "type alias",
|
ItemTy(..) => "type alias",
|
||||||
ItemEnum(..) => "enum",
|
ItemEnum(..) => "enum",
|
||||||
ItemStruct(..) => "struct",
|
ItemStruct(..) => "struct",
|
||||||
|
|
|
@ -633,6 +633,11 @@ impl<'a> State<'a> {
|
||||||
self.print_foreign_mod(nmod, &item.attrs)?;
|
self.print_foreign_mod(nmod, &item.attrs)?;
|
||||||
self.bclose(item.span)?;
|
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) => {
|
hir::ItemTy(ref ty, ref params) => {
|
||||||
self.ibox(indent_unit)?;
|
self.ibox(indent_unit)?;
|
||||||
self.ibox(0)?;
|
self.ibox(0)?;
|
||||||
|
|
|
@ -881,6 +881,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Item {
|
||||||
hir::ItemFn(..) |
|
hir::ItemFn(..) |
|
||||||
hir::ItemMod(..) |
|
hir::ItemMod(..) |
|
||||||
hir::ItemForeignMod(..) |
|
hir::ItemForeignMod(..) |
|
||||||
|
hir::ItemGlobalAsm(..) |
|
||||||
hir::ItemTy(..) |
|
hir::ItemTy(..) |
|
||||||
hir::ItemEnum(..) |
|
hir::ItemEnum(..) |
|
||||||
hir::ItemStruct(..) |
|
hir::ItemStruct(..) |
|
||||||
|
@ -925,6 +926,7 @@ impl_stable_hash_for!(enum hir::Item_ {
|
||||||
ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
|
ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
|
||||||
ItemMod(module),
|
ItemMod(module),
|
||||||
ItemForeignMod(foreign_mod),
|
ItemForeignMod(foreign_mod),
|
||||||
|
ItemGlobalAsm(global_asm),
|
||||||
ItemTy(ty, generics),
|
ItemTy(ty, generics),
|
||||||
ItemEnum(enum_def, generics),
|
ItemEnum(enum_def, generics),
|
||||||
ItemStruct(variant_data, generics),
|
ItemStruct(variant_data, generics),
|
||||||
|
@ -1014,6 +1016,19 @@ impl_stable_hash_for!(struct hir::InlineAsmOutput {
|
||||||
is_indirect
|
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 {
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::InlineAsm {
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
hcx: &mut StableHashingContext<'a, 'tcx>,
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
@ -1070,6 +1085,7 @@ impl_stable_hash_for!(enum hir::def::Def {
|
||||||
Upvar(def_id, index, expr_id),
|
Upvar(def_id, index, expr_id),
|
||||||
Label(node_id),
|
Label(node_id),
|
||||||
Macro(def_id, macro_kind),
|
Macro(def_id, macro_kind),
|
||||||
|
GlobalAsm(def_id),
|
||||||
Err
|
Err
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||||
hir::ItemMod(..) | hir::ItemForeignMod(..) |
|
hir::ItemMod(..) | hir::ItemForeignMod(..) |
|
||||||
hir::ItemImpl(..) | hir::ItemTrait(..) |
|
hir::ItemImpl(..) | hir::ItemTrait(..) |
|
||||||
hir::ItemStruct(..) | hir::ItemEnum(..) |
|
hir::ItemStruct(..) | hir::ItemEnum(..) |
|
||||||
hir::ItemUnion(..) | hir::ItemDefaultImpl(..) => {}
|
hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
|
||||||
|
hir::ItemGlobalAsm(..) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir_map::NodeTraitItem(trait_method) => {
|
hir_map::NodeTraitItem(trait_method) => {
|
||||||
|
|
|
@ -314,7 +314,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir::ItemUse(..) |
|
hir::ItemUse(..) |
|
||||||
hir::ItemMod(..) |
|
hir::ItemMod(..) |
|
||||||
hir::ItemDefaultImpl(..) |
|
hir::ItemDefaultImpl(..) |
|
||||||
hir::ItemForeignMod(..) => {
|
hir::ItemForeignMod(..) |
|
||||||
|
hir::ItemGlobalAsm(..) => {
|
||||||
// These sorts of items have no lifetime parameters at all.
|
// These sorts of items have no lifetime parameters at all.
|
||||||
intravisit::walk_item(self, item);
|
intravisit::walk_item(self, item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,6 +233,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
|
||||||
hir::ItemStatic(..) |
|
hir::ItemStatic(..) |
|
||||||
hir::ItemFn(..) |
|
hir::ItemFn(..) |
|
||||||
hir::ItemForeignMod(..) |
|
hir::ItemForeignMod(..) |
|
||||||
|
hir::ItemGlobalAsm(..) |
|
||||||
hir::ItemTy(..) => None,
|
hir::ItemTy(..) => None,
|
||||||
|
|
||||||
hir::ItemEnum(..) |
|
hir::ItemEnum(..) |
|
||||||
|
|
|
@ -507,6 +507,7 @@ extern "C" {
|
||||||
|
|
||||||
/// See Module::setModuleInlineAsm.
|
/// See Module::setModuleInlineAsm.
|
||||||
pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
|
pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
|
||||||
|
pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
|
||||||
|
|
||||||
/// See llvm::LLVMTypeKind::getTypeID.
|
/// See llvm::LLVMTypeKind::getTypeID.
|
||||||
pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
|
pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
|
||||||
|
|
|
@ -429,6 +429,7 @@ impl<'tcx> EntryKind<'tcx> {
|
||||||
EntryKind::Trait(_) => Def::Trait(did),
|
EntryKind::Trait(_) => Def::Trait(did),
|
||||||
EntryKind::Enum(..) => Def::Enum(did),
|
EntryKind::Enum(..) => Def::Enum(did),
|
||||||
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
|
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
|
||||||
|
EntryKind::GlobalAsm => Def::GlobalAsm(did),
|
||||||
|
|
||||||
EntryKind::ForeignMod |
|
EntryKind::ForeignMod |
|
||||||
EntryKind::Impl(_) |
|
EntryKind::Impl(_) |
|
||||||
|
|
|
@ -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)));
|
return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
|
||||||
}
|
}
|
||||||
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
|
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
|
||||||
|
hir::ItemGlobalAsm(..) => EntryKind::GlobalAsm,
|
||||||
hir::ItemTy(..) => EntryKind::Type,
|
hir::ItemTy(..) => EntryKind::Type,
|
||||||
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
|
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
|
||||||
hir::ItemStruct(ref struct_def, _) => {
|
hir::ItemStruct(ref struct_def, _) => {
|
||||||
|
@ -917,6 +918,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
hir::ItemFn(..) |
|
hir::ItemFn(..) |
|
||||||
hir::ItemMod(..) |
|
hir::ItemMod(..) |
|
||||||
hir::ItemForeignMod(..) |
|
hir::ItemForeignMod(..) |
|
||||||
|
hir::ItemGlobalAsm(..) |
|
||||||
hir::ItemExternCrate(..) |
|
hir::ItemExternCrate(..) |
|
||||||
hir::ItemUse(..) |
|
hir::ItemUse(..) |
|
||||||
hir::ItemDefaultImpl(..) |
|
hir::ItemDefaultImpl(..) |
|
||||||
|
|
|
@ -267,6 +267,7 @@ pub enum EntryKind<'tcx> {
|
||||||
ForeignImmStatic,
|
ForeignImmStatic,
|
||||||
ForeignMutStatic,
|
ForeignMutStatic,
|
||||||
ForeignMod,
|
ForeignMod,
|
||||||
|
GlobalAsm,
|
||||||
Type,
|
Type,
|
||||||
Enum(ReprOptions),
|
Enum(ReprOptions),
|
||||||
Field,
|
Field,
|
||||||
|
@ -297,6 +298,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for EntryKind<'tcx> {
|
||||||
EntryKind::ForeignImmStatic |
|
EntryKind::ForeignImmStatic |
|
||||||
EntryKind::ForeignMutStatic |
|
EntryKind::ForeignMutStatic |
|
||||||
EntryKind::ForeignMod |
|
EntryKind::ForeignMod |
|
||||||
|
EntryKind::GlobalAsm |
|
||||||
EntryKind::Field |
|
EntryKind::Field |
|
||||||
EntryKind::Type => {
|
EntryKind::Type => {
|
||||||
// Nothing else to hash here.
|
// Nothing else to hash here.
|
||||||
|
|
|
@ -160,7 +160,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
|
||||||
self.prev_level
|
self.prev_level
|
||||||
}
|
}
|
||||||
// Other `pub` items inherit levels from parents
|
// 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 }
|
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
|
// 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(..) => {}
|
hir::ItemUse(..) => {}
|
||||||
// The interface is empty
|
// The interface is empty
|
||||||
hir::ItemDefaultImpl(..) => {}
|
hir::ItemDefaultImpl(..) => {}
|
||||||
|
// The interface is empty
|
||||||
|
hir::ItemGlobalAsm(..) => {}
|
||||||
// Visit everything
|
// Visit everything
|
||||||
hir::ItemConst(..) | hir::ItemStatic(..) |
|
hir::ItemConst(..) | hir::ItemStatic(..) |
|
||||||
hir::ItemFn(..) | hir::ItemTy(..) => {
|
hir::ItemFn(..) | hir::ItemTy(..) => {
|
||||||
|
@ -1092,6 +1099,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
|
||||||
hir::ItemMod(..) => {}
|
hir::ItemMod(..) => {}
|
||||||
// Checked in resolve
|
// Checked in resolve
|
||||||
hir::ItemUse(..) => {}
|
hir::ItemUse(..) => {}
|
||||||
|
// No subitems
|
||||||
|
hir::ItemGlobalAsm(..) => {}
|
||||||
// Subitems of these items have inherited publicity
|
// Subitems of these items have inherited publicity
|
||||||
hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
|
hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
|
||||||
hir::ItemTy(..) => {
|
hir::ItemTy(..) => {
|
||||||
|
|
|
@ -268,6 +268,8 @@ impl<'a> Resolver<'a> {
|
||||||
self.define(parent, ident, TypeNS, imported_binding);
|
self.define(parent, ident, TypeNS, imported_binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemKind::GlobalAsm(..) => {}
|
||||||
|
|
||||||
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
|
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
|
||||||
|
|
||||||
ItemKind::Mod(..) => {
|
ItemKind::Mod(..) => {
|
||||||
|
|
|
@ -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
|
// do nothing, these are just around to be encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -341,6 +341,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||||
Def::AssociatedTy(..) |
|
Def::AssociatedTy(..) |
|
||||||
Def::AssociatedConst(..) |
|
Def::AssociatedConst(..) |
|
||||||
Def::PrimTy(_) |
|
Def::PrimTy(_) |
|
||||||
|
Def::GlobalAsm(_) |
|
||||||
Def::Err => {
|
Def::Err => {
|
||||||
span_bug!(span,
|
span_bug!(span,
|
||||||
"process_def_kind for unexpected item: {:?}",
|
"process_def_kind for unexpected item: {:?}",
|
||||||
|
|
|
@ -701,6 +701,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
Def::SelfTy(..) |
|
Def::SelfTy(..) |
|
||||||
Def::Label(..) |
|
Def::Label(..) |
|
||||||
Def::Macro(..) |
|
Def::Macro(..) |
|
||||||
|
Def::GlobalAsm(..) |
|
||||||
Def::Err => None,
|
Def::Err => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,3 +124,11 @@ pub fn trans_inline_asm<'a, 'tcx>(
|
||||||
llvm::LLVMMDNodeInContext(bcx.ccx.llcx(), &val, 1));
|
llvm::LLVMMDNodeInContext(bcx.ccx.llcx(), &val, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trans_global_asm<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
|
ga: &hir::GlobalAsm) {
|
||||||
|
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMRustAppendModuleInlineAsm(ccx.llmod(), asm.as_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -349,6 +349,9 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||||
|
|
||||||
collect_neighbours(scx, instance, &mut neighbors);
|
collect_neighbours(scx, instance, &mut neighbors);
|
||||||
}
|
}
|
||||||
|
TransItem::GlobalAsm(..) => {
|
||||||
|
recursion_depth_reset = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record_inlining_canditates(scx.tcx(), starting_point, &neighbors[..], inlining_map);
|
record_inlining_canditates(scx.tcx(), starting_point, &neighbors[..], inlining_map);
|
||||||
|
@ -840,6 +843,12 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hir::ItemGlobalAsm(..) => {
|
||||||
|
debug!("RootCollector: ItemGlobalAsm({})",
|
||||||
|
def_id_to_string(self.scx.tcx(),
|
||||||
|
self.scx.tcx().hir.local_def_id(item.id)));
|
||||||
|
self.output.push(TransItem::GlobalAsm(item.id));
|
||||||
|
}
|
||||||
hir::ItemStatic(..) => {
|
hir::ItemStatic(..) => {
|
||||||
debug!("RootCollector: ItemStatic({})",
|
debug!("RootCollector: ItemStatic({})",
|
||||||
def_id_to_string(self.scx.tcx(),
|
def_id_to_string(self.scx.tcx(),
|
||||||
|
|
|
@ -194,6 +194,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||||
TransItem::Static(node_id) => {
|
TransItem::Static(node_id) => {
|
||||||
exported_symbols.contains(&node_id)
|
exported_symbols.contains(&node_id)
|
||||||
}
|
}
|
||||||
|
TransItem::GlobalAsm(..) => true,
|
||||||
};
|
};
|
||||||
exported.hash(&mut state);
|
exported.hash(&mut state);
|
||||||
}
|
}
|
||||||
|
@ -243,7 +244,9 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||||
TransItem::Fn(instance) => {
|
TransItem::Fn(instance) => {
|
||||||
tcx.hir.as_local_node_id(instance.def_id())
|
tcx.hir.as_local_node_id(instance.def_id())
|
||||||
}
|
}
|
||||||
TransItem::Static(node_id) => Some(node_id),
|
TransItem::Static(node_id) | TransItem::GlobalAsm(node_id) => {
|
||||||
|
Some(node_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,7 +341,8 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||||
None => {
|
None => {
|
||||||
match trans_item {
|
match trans_item {
|
||||||
TransItem::Fn(..) |
|
TransItem::Fn(..) |
|
||||||
TransItem::Static(..) => llvm::ExternalLinkage,
|
TransItem::Static(..) |
|
||||||
|
TransItem::GlobalAsm(..) => llvm::ExternalLinkage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -483,7 +487,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 't
|
||||||
|
|
||||||
Some(def_id)
|
Some(def_id)
|
||||||
}
|
}
|
||||||
TransItem::Static(node_id) => Some(tcx.hir.local_def_id(node_id)),
|
TransItem::Static(node_id) |
|
||||||
|
TransItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,10 @@ impl<'tcx> SymbolMap<'tcx> {
|
||||||
TransItem::Fn(Instance { def, .. }) => {
|
TransItem::Fn(Instance { def, .. }) => {
|
||||||
tcx.hir.as_local_node_id(def.def_id())
|
tcx.hir.as_local_node_id(def.def_id())
|
||||||
}
|
}
|
||||||
TransItem::Static(node_id) => Some(node_id),
|
TransItem::Static(node_id) |
|
||||||
|
TransItem::GlobalAsm(node_id) => {
|
||||||
|
Some(node_id)
|
||||||
|
}
|
||||||
}.map(|node_id| {
|
}.map(|node_id| {
|
||||||
tcx.hir.span(node_id)
|
tcx.hir.span(node_id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
//! item-path. This is used for unit testing the code that generates
|
//! item-path. This is used for unit testing the code that generates
|
||||||
//! paths etc in all kinds of annoying scenarios.
|
//! paths etc in all kinds of annoying scenarios.
|
||||||
|
|
||||||
|
use asm;
|
||||||
use attributes;
|
use attributes;
|
||||||
use base;
|
use base;
|
||||||
use consts;
|
use consts;
|
||||||
|
@ -38,7 +39,8 @@ use std::iter;
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
||||||
pub enum TransItem<'tcx> {
|
pub enum TransItem<'tcx> {
|
||||||
Fn(Instance<'tcx>),
|
Fn(Instance<'tcx>),
|
||||||
Static(NodeId)
|
Static(NodeId),
|
||||||
|
GlobalAsm(NodeId),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes how a translation item will be instantiated in object files.
|
/// Describes how a translation item will be instantiated in object files.
|
||||||
|
@ -89,6 +91,14 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
|
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TransItem::GlobalAsm(node_id) => {
|
||||||
|
let item = ccx.tcx().hir.expect_item(node_id);
|
||||||
|
if let hir::ItemGlobalAsm(ref ga) = item.node {
|
||||||
|
asm::trans_global_asm(ccx, ga);
|
||||||
|
} else {
|
||||||
|
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
|
||||||
|
}
|
||||||
|
}
|
||||||
TransItem::Fn(instance) => {
|
TransItem::Fn(instance) => {
|
||||||
let _task = ccx.tcx().dep_graph.in_task(
|
let _task = ccx.tcx().dep_graph.in_task(
|
||||||
DepNode::TransCrateItem(instance.def_id())); // (*)
|
DepNode::TransCrateItem(instance.def_id())); // (*)
|
||||||
|
@ -123,6 +133,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
TransItem::Fn(instance) => {
|
TransItem::Fn(instance) => {
|
||||||
TransItem::predefine_fn(ccx, instance, linkage, &symbol_name);
|
TransItem::predefine_fn(ccx, instance, linkage, &symbol_name);
|
||||||
}
|
}
|
||||||
|
TransItem::GlobalAsm(..) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("END PREDEFINING '{} ({})' in cgu {}",
|
debug!("END PREDEFINING '{} ({})' in cgu {}",
|
||||||
|
@ -185,6 +196,10 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
let def_id = scx.tcx().hir.local_def_id(node_id);
|
let def_id = scx.tcx().hir.local_def_id(node_id);
|
||||||
symbol_names::symbol_name(Instance::mono(scx.tcx(), def_id), scx)
|
symbol_names::symbol_name(Instance::mono(scx.tcx(), def_id), scx)
|
||||||
}
|
}
|
||||||
|
TransItem::GlobalAsm(node_id) => {
|
||||||
|
let def_id = scx.tcx().hir.local_def_id(node_id);
|
||||||
|
format!("global_asm_{:?}", def_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +217,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TransItem::Static(..) => InstantiationMode::GloballyShared,
|
TransItem::Static(..) => InstantiationMode::GloballyShared,
|
||||||
|
TransItem::GlobalAsm(..) => InstantiationMode::GloballyShared,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +226,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
TransItem::Fn(ref instance) => {
|
TransItem::Fn(ref instance) => {
|
||||||
instance.substs.types().next().is_some()
|
instance.substs.types().next().is_some()
|
||||||
}
|
}
|
||||||
TransItem::Static(..) => false,
|
TransItem::Static(..) |
|
||||||
|
TransItem::GlobalAsm(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +235,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
let def_id = match *self {
|
let def_id = match *self {
|
||||||
TransItem::Fn(ref instance) => instance.def_id(),
|
TransItem::Fn(ref instance) => instance.def_id(),
|
||||||
TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
|
TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
|
||||||
|
TransItem::GlobalAsm(..) => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let attributes = tcx.get_attrs(def_id);
|
let attributes = tcx.get_attrs(def_id);
|
||||||
|
@ -249,6 +267,9 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
|
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
|
||||||
to_string_internal(tcx, "static ", instance)
|
to_string_internal(tcx, "static ", instance)
|
||||||
},
|
},
|
||||||
|
TransItem::GlobalAsm(..) => {
|
||||||
|
"global_asm".to_string()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
@ -273,6 +294,9 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
TransItem::Static(id) => {
|
TransItem::Static(id) => {
|
||||||
format!("Static({:?})", id)
|
format!("Static({:?})", id)
|
||||||
}
|
}
|
||||||
|
TransItem::GlobalAsm(id) => {
|
||||||
|
format!("GlobalAsm({:?})", id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -490,8 +490,10 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
|
||||||
let def_id = tcx.hir.local_def_id(item_id);
|
let def_id = tcx.hir.local_def_id(item_id);
|
||||||
match it.node {
|
match it.node {
|
||||||
// These don't define types.
|
// These don't define types.
|
||||||
hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => {
|
hir::ItemExternCrate(_) |
|
||||||
}
|
hir::ItemUse(..) |
|
||||||
|
hir::ItemMod(_) |
|
||||||
|
hir::ItemGlobalAsm(_) => {}
|
||||||
hir::ItemForeignMod(ref foreign_mod) => {
|
hir::ItemForeignMod(ref foreign_mod) => {
|
||||||
for item in &foreign_mod.items {
|
for item in &foreign_mod.items {
|
||||||
let def_id = tcx.hir.local_def_id(item.id);
|
let def_id = tcx.hir.local_def_id(item.id);
|
||||||
|
@ -543,12 +545,12 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
|
||||||
tcx.item_generics(def_id);
|
tcx.item_generics(def_id);
|
||||||
tcx.item_type(def_id);
|
tcx.item_type(def_id);
|
||||||
tcx.item_predicates(def_id);
|
tcx.item_predicates(def_id);
|
||||||
},
|
}
|
||||||
_ => {
|
hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => {
|
||||||
tcx.item_generics(def_id);
|
tcx.item_generics(def_id);
|
||||||
tcx.item_type(def_id);
|
tcx.item_type(def_id);
|
||||||
tcx.item_predicates(def_id);
|
tcx.item_predicates(def_id);
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,6 +1076,7 @@ fn ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
ItemTrait(..) |
|
ItemTrait(..) |
|
||||||
ItemMod(..) |
|
ItemMod(..) |
|
||||||
ItemForeignMod(..) |
|
ItemForeignMod(..) |
|
||||||
|
ItemGlobalAsm(..) |
|
||||||
ItemExternCrate(..) |
|
ItemExternCrate(..) |
|
||||||
ItemUse(..) => {
|
ItemUse(..) => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
|
|
|
@ -113,6 +113,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
|
||||||
hir::ItemFn(..) |
|
hir::ItemFn(..) |
|
||||||
hir::ItemMod(..) |
|
hir::ItemMod(..) |
|
||||||
hir::ItemForeignMod(..) |
|
hir::ItemForeignMod(..) |
|
||||||
|
hir::ItemGlobalAsm(..) |
|
||||||
hir::ItemTy(..) |
|
hir::ItemTy(..) |
|
||||||
hir::ItemImpl(..) |
|
hir::ItemImpl(..) |
|
||||||
hir::ItemDefaultImpl(..) => {}
|
hir::ItemDefaultImpl(..) => {}
|
||||||
|
|
|
@ -251,6 +251,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
|
||||||
hir::ItemFn(..) |
|
hir::ItemFn(..) |
|
||||||
hir::ItemMod(..) |
|
hir::ItemMod(..) |
|
||||||
hir::ItemForeignMod(..) |
|
hir::ItemForeignMod(..) |
|
||||||
|
hir::ItemGlobalAsm(..) |
|
||||||
hir::ItemTy(..) => {}
|
hir::ItemTy(..) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,6 +373,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
// If we're inlining, skip private items.
|
// If we're inlining, skip private items.
|
||||||
_ if self.inlining && item.vis != hir::Public => {}
|
_ if self.inlining && item.vis != hir::Public => {}
|
||||||
|
hir::ItemGlobalAsm(..) => {}
|
||||||
hir::ItemExternCrate(ref p) => {
|
hir::ItemExternCrate(ref p) => {
|
||||||
let cstore = &self.cx.sess().cstore;
|
let cstore = &self.cx.sess().cstore;
|
||||||
om.extern_crates.push(ExternCrate {
|
om.extern_crates.push(ExternCrate {
|
||||||
|
|
|
@ -1585,6 +1585,15 @@ pub struct ForeignMod {
|
||||||
pub items: Vec<ForeignItem>,
|
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)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub struct EnumDef {
|
pub struct EnumDef {
|
||||||
pub variants: Vec<Variant>,
|
pub variants: Vec<Variant>,
|
||||||
|
@ -1812,6 +1821,8 @@ pub enum ItemKind {
|
||||||
///
|
///
|
||||||
/// E.g. `extern {}` or `extern "C" {}`
|
/// E.g. `extern {}` or `extern "C" {}`
|
||||||
ForeignMod(ForeignMod),
|
ForeignMod(ForeignMod),
|
||||||
|
/// Module-level inline assembly (from `global_asm!()`)
|
||||||
|
GlobalAsm(P<GlobalAsm>),
|
||||||
/// A type alias (`type` or `pub type`).
|
/// A type alias (`type` or `pub type`).
|
||||||
///
|
///
|
||||||
/// E.g. `type Foo = Bar<u8>;`
|
/// E.g. `type Foo = Bar<u8>;`
|
||||||
|
@ -1864,6 +1875,7 @@ impl ItemKind {
|
||||||
ItemKind::Fn(..) => "function",
|
ItemKind::Fn(..) => "function",
|
||||||
ItemKind::Mod(..) => "module",
|
ItemKind::Mod(..) => "module",
|
||||||
ItemKind::ForeignMod(..) => "foreign module",
|
ItemKind::ForeignMod(..) => "foreign module",
|
||||||
|
ItemKind::GlobalAsm(..) => "global asm",
|
||||||
ItemKind::Ty(..) => "type alias",
|
ItemKind::Ty(..) => "type alias",
|
||||||
ItemKind::Enum(..) => "enum",
|
ItemKind::Enum(..) => "enum",
|
||||||
ItemKind::Struct(..) => "struct",
|
ItemKind::Struct(..) => "struct",
|
||||||
|
|
|
@ -1039,6 +1039,7 @@ impl<'feat> ExpansionConfig<'feat> {
|
||||||
feature_tests! {
|
feature_tests! {
|
||||||
fn enable_quotes = quote,
|
fn enable_quotes = quote,
|
||||||
fn enable_asm = asm,
|
fn enable_asm = asm,
|
||||||
|
fn enable_global_asm = global_asm,
|
||||||
fn enable_log_syntax = log_syntax,
|
fn enable_log_syntax = log_syntax,
|
||||||
fn enable_concat_idents = concat_idents,
|
fn enable_concat_idents = concat_idents,
|
||||||
fn enable_trace_macros = trace_macros,
|
fn enable_trace_macros = trace_macros,
|
||||||
|
|
|
@ -346,6 +346,9 @@ declare_features! (
|
||||||
|
|
||||||
// Hack to document `-Z linker-flavor` in The Unstable Book
|
// Hack to document `-Z linker-flavor` in The Unstable Book
|
||||||
(active, linker_flavor, "1.18.0", Some(41142)),
|
(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! (
|
declare_features! (
|
||||||
|
@ -982,6 +985,9 @@ pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
|
||||||
pub const EXPLAIN_ASM: &'static str =
|
pub const EXPLAIN_ASM: &'static str =
|
||||||
"inline assembly is not stable enough for use and is subject to change";
|
"inline assembly is not stable enough for use and is subject to change";
|
||||||
|
|
||||||
|
pub const EXPLAIN_GLOBAL_ASM: &'static str =
|
||||||
|
"`global_asm!` is not stable enough for use and is subject to change";
|
||||||
|
|
||||||
pub const EXPLAIN_LOG_SYNTAX: &'static str =
|
pub const EXPLAIN_LOG_SYNTAX: &'static str =
|
||||||
"`log_syntax!` is not stable enough for use and is subject to change";
|
"`log_syntax!` is not stable enough for use and is subject to change";
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,10 @@ pub trait Folder : Sized {
|
||||||
noop_fold_foreign_mod(nm, self)
|
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 {
|
fn fold_variant(&mut self, v: Variant) -> Variant {
|
||||||
noop_fold_variant(v, self)
|
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 {
|
pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
|
||||||
Spanned {
|
Spanned {
|
||||||
node: Variant_ {
|
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::Mod(m) => ItemKind::Mod(folder.fold_mod(m)),
|
||||||
ItemKind::ForeignMod(nm) => ItemKind::ForeignMod(folder.fold_foreign_mod(nm)),
|
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(t, generics) => {
|
||||||
ItemKind::Ty(folder.fold_ty(t), folder.fold_generics(generics))
|
ItemKind::Ty(folder.fold_ty(t), folder.fold_generics(generics))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1267,6 +1267,11 @@ impl<'a> State<'a> {
|
||||||
self.print_foreign_mod(nmod, &item.attrs)?;
|
self.print_foreign_mod(nmod, &item.attrs)?;
|
||||||
self.bclose(item.span)?;
|
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) => {
|
ast::ItemKind::Ty(ref ty, ref params) => {
|
||||||
self.ibox(INDENT_UNIT)?;
|
self.ibox(INDENT_UNIT)?;
|
||||||
self.ibox(0)?;
|
self.ibox(0)?;
|
||||||
|
|
|
@ -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_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_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_item(&mut self, i: &'ast Item) { walk_item(self, i) }
|
||||||
fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
|
fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
|
||||||
fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
|
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) => {
|
ItemKind::ForeignMod(ref foreign_module) => {
|
||||||
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
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) => {
|
ItemKind::Ty(ref typ, ref type_parameters) => {
|
||||||
visitor.visit_ty(typ);
|
visitor.visit_ty(typ);
|
||||||
visitor.visit_generics(type_parameters)
|
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);
|
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) {
|
pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) {
|
||||||
match *bound {
|
match *bound {
|
||||||
TraitTyParamBound(ref typ, ref modifier) => {
|
TraitTyParamBound(ref typ, ref modifier) => {
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
// 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::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,
|
||||||
|
})))
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ mod concat_idents;
|
||||||
mod env;
|
mod env;
|
||||||
mod format;
|
mod format;
|
||||||
mod format_foreign;
|
mod format_foreign;
|
||||||
|
mod global_asm;
|
||||||
mod log_syntax;
|
mod log_syntax;
|
||||||
mod trace_macros;
|
mod trace_macros;
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
|
||||||
module_path: expand_mod,
|
module_path: expand_mod,
|
||||||
|
|
||||||
asm: asm::expand_asm,
|
asm: asm::expand_asm,
|
||||||
|
global_asm: global_asm::expand_global_asm,
|
||||||
cfg: cfg::expand_cfg,
|
cfg: cfg::expand_cfg,
|
||||||
concat: concat::expand_syntax_ext,
|
concat: concat::expand_syntax_ext,
|
||||||
concat_idents: concat_idents::expand_syntax_ext,
|
concat_idents: concat_idents::expand_syntax_ext,
|
||||||
|
|
|
@ -312,6 +312,10 @@ extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString,
|
||||||
HasSideEffects, IsAlignStack, fromRust(Dialect)));
|
HasSideEffects, IsAlignStack, fromRust(Dialect)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm) {
|
||||||
|
unwrap(M)->appendModuleInlineAsm(StringRef(Asm));
|
||||||
|
}
|
||||||
|
|
||||||
typedef DIBuilder *LLVMRustDIBuilderRef;
|
typedef DIBuilder *LLVMRustDIBuilderRef;
|
||||||
|
|
||||||
typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
|
typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
.global foo
|
||||||
|
foo:
|
||||||
|
jmp baz
|
|
@ -0,0 +1,73 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// ignore-aarch64
|
||||||
|
// ignore-aarch64_be
|
||||||
|
// ignore-arm
|
||||||
|
// ignore-armeb
|
||||||
|
// ignore-avr
|
||||||
|
// ignore-bpfel
|
||||||
|
// ignore-bpfeb
|
||||||
|
// ignore-hexagon
|
||||||
|
// ignore-mips
|
||||||
|
// ignore-mipsel
|
||||||
|
// ignore-mips64
|
||||||
|
// ignore-mips64el
|
||||||
|
// ignore-msp430
|
||||||
|
// ignore-powerpc64
|
||||||
|
// ignore-powerpc64le
|
||||||
|
// ignore-powerpc
|
||||||
|
// ignore-r600
|
||||||
|
// ignore-amdgcn
|
||||||
|
// ignore-sparc
|
||||||
|
// ignore-sparcv9
|
||||||
|
// ignore-sparcel
|
||||||
|
// ignore-s390x
|
||||||
|
// ignore-tce
|
||||||
|
// ignore-thumb
|
||||||
|
// ignore-thumbeb
|
||||||
|
// ignore-xcore
|
||||||
|
// ignore-nvptx
|
||||||
|
// ignore-nvptx64
|
||||||
|
// ignore-le32
|
||||||
|
// ignore-le64
|
||||||
|
// ignore-amdil
|
||||||
|
// ignore-amdil64
|
||||||
|
// ignore-hsail
|
||||||
|
// ignore-hsail64
|
||||||
|
// ignore-spir
|
||||||
|
// ignore-spir64
|
||||||
|
// ignore-kalimba
|
||||||
|
// ignore-shave
|
||||||
|
// ignore-wasm32
|
||||||
|
// ignore-wasm64
|
||||||
|
// ignore-emscripten
|
||||||
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
|
||||||
|
#![feature(global_asm)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// CHECK-LABEL: foo
|
||||||
|
// CHECK: module asm
|
||||||
|
// this regex will capture the correct unconditional branch inst.
|
||||||
|
// CHECK: module asm "{{[[:space:]]+}}jmp baz"
|
||||||
|
global_asm!(r#"
|
||||||
|
.global foo
|
||||||
|
foo:
|
||||||
|
jmp baz
|
||||||
|
"#);
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @baz
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn baz() {}
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// ignore-aarch64
|
||||||
|
// ignore-aarch64_be
|
||||||
|
// ignore-arm
|
||||||
|
// ignore-armeb
|
||||||
|
// ignore-avr
|
||||||
|
// ignore-bpfel
|
||||||
|
// ignore-bpfeb
|
||||||
|
// ignore-hexagon
|
||||||
|
// ignore-mips
|
||||||
|
// ignore-mipsel
|
||||||
|
// ignore-mips64
|
||||||
|
// ignore-mips64el
|
||||||
|
// ignore-msp430
|
||||||
|
// ignore-powerpc64
|
||||||
|
// ignore-powerpc64le
|
||||||
|
// ignore-powerpc
|
||||||
|
// ignore-r600
|
||||||
|
// ignore-amdgcn
|
||||||
|
// ignore-sparc
|
||||||
|
// ignore-sparcv9
|
||||||
|
// ignore-sparcel
|
||||||
|
// ignore-s390x
|
||||||
|
// ignore-tce
|
||||||
|
// ignore-thumb
|
||||||
|
// ignore-thumbeb
|
||||||
|
// ignore-xcore
|
||||||
|
// ignore-nvptx
|
||||||
|
// ignore-nvptx64
|
||||||
|
// ignore-le32
|
||||||
|
// ignore-le64
|
||||||
|
// ignore-amdil
|
||||||
|
// ignore-amdil64
|
||||||
|
// ignore-hsail
|
||||||
|
// ignore-hsail64
|
||||||
|
// ignore-spir
|
||||||
|
// ignore-spir64
|
||||||
|
// ignore-kalimba
|
||||||
|
// ignore-shave
|
||||||
|
// ignore-wasm32
|
||||||
|
// ignore-wasm64
|
||||||
|
// ignore-emscripten
|
||||||
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
|
||||||
|
#![feature(global_asm)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// CHECK-LABEL: foo
|
||||||
|
// CHECK: module asm
|
||||||
|
// CHECK: module asm "{{[[:space:]]+}}jmp baz"
|
||||||
|
global_asm!(include_str!("foo.s"));
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @baz
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn baz() {}
|
|
@ -0,0 +1,90 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// ignore-aarch64
|
||||||
|
// ignore-aarch64_be
|
||||||
|
// ignore-arm
|
||||||
|
// ignore-armeb
|
||||||
|
// ignore-avr
|
||||||
|
// ignore-bpfel
|
||||||
|
// ignore-bpfeb
|
||||||
|
// ignore-hexagon
|
||||||
|
// ignore-mips
|
||||||
|
// ignore-mipsel
|
||||||
|
// ignore-mips64
|
||||||
|
// ignore-mips64el
|
||||||
|
// ignore-msp430
|
||||||
|
// ignore-powerpc64
|
||||||
|
// ignore-powerpc64le
|
||||||
|
// ignore-powerpc
|
||||||
|
// ignore-r600
|
||||||
|
// ignore-amdgcn
|
||||||
|
// ignore-sparc
|
||||||
|
// ignore-sparcv9
|
||||||
|
// ignore-sparcel
|
||||||
|
// ignore-s390x
|
||||||
|
// ignore-tce
|
||||||
|
// ignore-thumb
|
||||||
|
// ignore-thumbeb
|
||||||
|
// ignore-xcore
|
||||||
|
// ignore-nvptx
|
||||||
|
// ignore-nvptx64
|
||||||
|
// ignore-le32
|
||||||
|
// ignore-le64
|
||||||
|
// ignore-amdil
|
||||||
|
// ignore-amdil64
|
||||||
|
// ignore-hsail
|
||||||
|
// ignore-hsail64
|
||||||
|
// ignore-spir
|
||||||
|
// ignore-spir64
|
||||||
|
// ignore-kalimba
|
||||||
|
// ignore-shave
|
||||||
|
// ignore-wasm32
|
||||||
|
// ignore-wasm64
|
||||||
|
// ignore-emscripten
|
||||||
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
|
||||||
|
#![feature(global_asm)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#[no_std]
|
||||||
|
|
||||||
|
// CHECK-LABEL: foo
|
||||||
|
// CHECK: module asm
|
||||||
|
// CHECK: module asm "{{[[:space:]]+}}jmp baz"
|
||||||
|
// any other global_asm will be appended to this first block, so:
|
||||||
|
// CHECK-LABEL: bar
|
||||||
|
// CHECK: module asm "{{[[:space:]]+}}jmp quux"
|
||||||
|
global_asm!(r#"
|
||||||
|
.global foo
|
||||||
|
foo:
|
||||||
|
jmp baz
|
||||||
|
"#);
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @baz
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn baz() {}
|
||||||
|
|
||||||
|
// no checks here; this has been appended to the first occurrence
|
||||||
|
global_asm!(r#"
|
||||||
|
.global bar
|
||||||
|
bar:
|
||||||
|
jmp quux
|
||||||
|
"#);
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn quux() {}
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// gate-test-global_asm
|
||||||
|
|
||||||
|
global_asm!(""); //~ ERROR `global_asm!` is not stable
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
#![feature(global_asm)]
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
global_asm!("");
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
global_asm!("");
|
||||||
|
|
||||||
|
#[cfg(target_arch = "arm")]
|
||||||
|
global_asm!("");
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
global_asm!("");
|
||||||
|
|
||||||
|
#[cfg(target_arch = "mips")]
|
||||||
|
global_asm!("");
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
#![feature(global_asm)]
|
||||||
|
#![feature(naked_functions)]
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
|
||||||
|
global_asm!(r#"
|
||||||
|
.global foo
|
||||||
|
.global _foo
|
||||||
|
foo:
|
||||||
|
_foo:
|
||||||
|
ret
|
||||||
|
"#);
|
||||||
|
|
||||||
|
extern {
|
||||||
|
fn foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
|
||||||
|
fn main() { unsafe { foo(); } }
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue