Skip to content

Commit 99b81e5

Browse files
authored
Rollup merge of rust-lang#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: rust-lang#35119
2 parents 9e84bf8 + 57bd395 commit 99b81e5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+631
-25
lines changed

src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
- [future_atomic_orderings](future-atomic-orderings.md)
8282
- [generic_param_attrs](generic-param-attrs.md)
8383
- [get_type_id](get-type-id.md)
84+
- [global_asm](global_asm.md)
8485
- [heap_api](heap-api.md)
8586
- [i128](i128.md)
8687
- [i128_type](i128-type.md)

src/doc/unstable-book/src/asm.md

+2
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,5 @@ constraints, etc.
189189

190190
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
191191

192+
If you need more power and don't mind losing some of the niceties of
193+
`asm!`, check out [global_asm](global_asm.html).
+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# `global_asm`
2+
3+
The tracking issue for this feature is: [#35119]
4+
5+
[#35119]: https://github.com/rust-lang/rust/issues/35119
6+
7+
------------------------
8+
9+
The `global_asm!` macro allows the programmer to write arbitrary
10+
assembly outside the scope of a function body, passing it through
11+
`rustc` and `llvm` to the assembler. The macro is a no-frills
12+
interface to LLVM's concept of [module-level inline assembly]. That is,
13+
all caveats applicable to LLVM's module-level inline assembly apply
14+
to `global_asm!`.
15+
16+
[module-level inline assembly]: http://llvm.org/docs/LangRef.html#module-level-inline-assembly
17+
18+
`global_asm!` fills a role not currently satisfied by either `asm!`
19+
or `#[naked]` functions. The programmer has _all_ features of the
20+
assembler at their disposal. The linker will expect to resolve any
21+
symbols defined in the inline assembly, modulo any symbols marked as
22+
external. It also means syntax for directives and assembly follow the
23+
conventions of the assembler in your toolchain.
24+
25+
A simple usage looks like this:
26+
27+
```rust,ignore
28+
# #![feature(global_asm)]
29+
# you also need relevant target_arch cfgs
30+
global_asm!(include_str!("something_neato.s"));
31+
```
32+
33+
And a more complicated usage looks like this:
34+
35+
```rust,ignore
36+
# #![feature(global_asm)]
37+
# #![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
38+
39+
pub mod sally {
40+
global_asm!(r#"
41+
.global foo
42+
foo:
43+
jmp baz
44+
"#);
45+
46+
#[no_mangle]
47+
pub unsafe extern "C" fn baz() {}
48+
}
49+
50+
// the symbols `foo` and `bar` are global, no matter where
51+
// `global_asm!` was used.
52+
extern "C" {
53+
fn foo();
54+
fn bar();
55+
}
56+
57+
pub mod harry {
58+
global_asm!(r#"
59+
.global bar
60+
bar:
61+
jmp quux
62+
"#);
63+
64+
#[no_mangle]
65+
pub unsafe extern "C" fn quux() {}
66+
}
67+
```
68+
69+
You may use `global_asm!` multiple times, anywhere in your crate, in
70+
whatever way suits you. The effect is as if you concatenated all
71+
usages and placed the larger, single usage in the crate root.
72+
73+
------------------------
74+
75+
If you don't need quite as much power and flexibility as
76+
`global_asm!` provides, and you don't mind restricting your inline
77+
assembly to `fn` bodies only, you might try the [asm](asm.html)
78+
feature instead.

src/librustc/hir/def.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ pub enum Def {
5757
// Macro namespace
5858
Macro(DefId, MacroKind),
5959

60+
GlobalAsm(DefId),
61+
6062
// Both namespaces
6163
Err,
6264
}
@@ -144,7 +146,8 @@ impl Def {
144146
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
145147
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
146148
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
147-
Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) => {
149+
Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) |
150+
Def::GlobalAsm(id) => {
148151
id
149152
}
150153

@@ -185,6 +188,7 @@ impl Def {
185188
Def::Label(..) => "label",
186189
Def::SelfTy(..) => "self type",
187190
Def::Macro(..) => "macro",
191+
Def::GlobalAsm(..) => "global asm",
188192
Def::Err => "unresolved item",
189193
}
190194
}

src/librustc/hir/intravisit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
474474
visitor.visit_id(item.id);
475475
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
476476
}
477+
ItemGlobalAsm(_) => {
478+
visitor.visit_id(item.id);
479+
}
477480
ItemTy(ref typ, ref type_parameters) => {
478481
visitor.visit_id(item.id);
479482
visitor.visit_ty(typ);

src/librustc/hir/lowering.rs

+8
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,13 @@ impl<'a> LoweringContext<'a> {
645645
}
646646
}
647647

648+
fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
649+
P(hir::GlobalAsm {
650+
asm: ga.asm,
651+
ctxt: ga.ctxt,
652+
})
653+
}
654+
648655
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
649656
Spanned {
650657
node: hir::Variant_ {
@@ -1287,6 +1294,7 @@ impl<'a> LoweringContext<'a> {
12871294
}
12881295
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
12891296
ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
1297+
ItemKind::GlobalAsm(ref ga) => hir::ItemGlobalAsm(self.lower_global_asm(ga)),
12901298
ItemKind::Ty(ref t, ref generics) => {
12911299
hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
12921300
}

src/librustc/hir/map/def_collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
120120
DefPathData::ValueNs(i.ident.name.as_str()),
121121
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
122122
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
123+
ItemKind::GlobalAsm(..) => DefPathData::Misc,
123124
ItemKind::Use(ref view_path) => {
124125
match view_path.node {
125126
ViewPathGlob(..) => {}

src/librustc/hir/map/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
10561056
ItemFn(..) => "fn",
10571057
ItemMod(..) => "mod",
10581058
ItemForeignMod(..) => "foreign mod",
1059+
ItemGlobalAsm(..) => "global asm",
10591060
ItemTy(..) => "ty",
10601061
ItemEnum(..) => "enum",
10611062
ItemStruct(..) => "struct",

src/librustc/hir/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,12 @@ pub struct ForeignMod {
14931493
pub items: HirVec<ForeignItem>,
14941494
}
14951495

1496+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
1497+
pub struct GlobalAsm {
1498+
pub asm: Symbol,
1499+
pub ctxt: SyntaxContext
1500+
}
1501+
14961502
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
14971503
pub struct EnumDef {
14981504
pub variants: HirVec<Variant>,
@@ -1684,6 +1690,8 @@ pub enum Item_ {
16841690
ItemMod(Mod),
16851691
/// An external module
16861692
ItemForeignMod(ForeignMod),
1693+
/// Module-level inline assembly (from global_asm!)
1694+
ItemGlobalAsm(P<GlobalAsm>),
16871695
/// A type alias, e.g. `type Foo = Bar<u8>`
16881696
ItemTy(P<Ty>, Generics),
16891697
/// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
@@ -1718,6 +1726,7 @@ impl Item_ {
17181726
ItemFn(..) => "function",
17191727
ItemMod(..) => "module",
17201728
ItemForeignMod(..) => "foreign module",
1729+
ItemGlobalAsm(..) => "global asm",
17211730
ItemTy(..) => "type alias",
17221731
ItemEnum(..) => "enum",
17231732
ItemStruct(..) => "struct",

src/librustc/hir/print.rs

+5
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,11 @@ impl<'a> State<'a> {
630630
self.print_foreign_mod(nmod, &item.attrs)?;
631631
self.bclose(item.span)?;
632632
}
633+
hir::ItemGlobalAsm(ref ga) => {
634+
self.head(&visibility_qualified(&item.vis, "global asm"))?;
635+
word(&mut self.s, &ga.asm.as_str())?;
636+
self.end()?
637+
}
633638
hir::ItemTy(ref ty, ref params) => {
634639
self.ibox(indent_unit)?;
635640
self.ibox(0)?;

src/librustc/middle/reachable.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
267267
hir::ItemMod(..) | hir::ItemForeignMod(..) |
268268
hir::ItemImpl(..) | hir::ItemTrait(..) |
269269
hir::ItemStruct(..) | hir::ItemEnum(..) |
270-
hir::ItemUnion(..) | hir::ItemDefaultImpl(..) => {}
270+
hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
271+
hir::ItemGlobalAsm(..) => {}
271272
}
272273
}
273274
hir_map::NodeTraitItem(trait_method) => {

src/librustc/middle/resolve_lifetime.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
314314
hir::ItemUse(..) |
315315
hir::ItemMod(..) |
316316
hir::ItemDefaultImpl(..) |
317-
hir::ItemForeignMod(..) => {
317+
hir::ItemForeignMod(..) |
318+
hir::ItemGlobalAsm(..) => {
318319
// These sorts of items have no lifetime parameters at all.
319320
intravisit::walk_item(self, item);
320321
}

src/librustc_driver/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
233233
hir::ItemStatic(..) |
234234
hir::ItemFn(..) |
235235
hir::ItemForeignMod(..) |
236+
hir::ItemGlobalAsm(..) |
236237
hir::ItemTy(..) => None,
237238

238239
hir::ItemEnum(..) |

src/librustc_incremental/calculate_svh/svh_visitor.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ enum SawItemComponent {
354354
SawItemFn(Unsafety, Constness, Abi),
355355
SawItemMod,
356356
SawItemForeignMod(Abi),
357+
SawItemGlobalAsm,
357358
SawItemTy,
358359
SawItemEnum,
359360
SawItemStruct,
@@ -372,6 +373,7 @@ fn saw_item(node: &Item_) -> SawItemComponent {
372373
ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi),
373374
ItemMod(..) => SawItemMod,
374375
ItemForeignMod(ref fm) => SawItemForeignMod(fm.abi),
376+
ItemGlobalAsm(..) => SawItemGlobalAsm,
375377
ItemTy(..) => SawItemTy,
376378
ItemEnum(..) => SawItemEnum,
377379
ItemStruct(..) => SawItemStruct,
@@ -920,7 +922,8 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
920922
Def::AssociatedConst(..) |
921923
Def::Local(..) |
922924
Def::Upvar(..) |
923-
Def::Macro(..) => {
925+
Def::Macro(..) |
926+
Def::GlobalAsm(..) => {
924927
DefHash::SawDefId.hash(self.st);
925928
self.hash_def_id(def.def_id());
926929
}

src/librustc_llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ extern "C" {
507507

508508
/// See Module::setModuleInlineAsm.
509509
pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
510+
pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
510511

511512
/// See llvm::LLVMTypeKind::getTypeID.
512513
pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;

src/librustc_metadata/decoder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ impl<'tcx> EntryKind<'tcx> {
429429
EntryKind::Trait(_) => Def::Trait(did),
430430
EntryKind::Enum(..) => Def::Enum(did),
431431
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
432+
EntryKind::GlobalAsm => Def::GlobalAsm(did),
432433

433434
EntryKind::ForeignMod |
434435
EntryKind::Impl(_) |

src/librustc_metadata/encoder.rs

+2
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
655655
return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
656656
}
657657
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
658+
hir::ItemGlobalAsm(..) => EntryKind::GlobalAsm,
658659
hir::ItemTy(..) => EntryKind::Type,
659660
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
660661
hir::ItemStruct(ref struct_def, _) => {
@@ -895,6 +896,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
895896
hir::ItemFn(..) |
896897
hir::ItemMod(..) |
897898
hir::ItemForeignMod(..) |
899+
hir::ItemGlobalAsm(..) |
898900
hir::ItemExternCrate(..) |
899901
hir::ItemUse(..) |
900902
hir::ItemDefaultImpl(..) |

src/librustc_metadata/schema.rs

+1
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ pub enum EntryKind<'tcx> {
227227
ForeignImmStatic,
228228
ForeignMutStatic,
229229
ForeignMod,
230+
GlobalAsm,
230231
Type,
231232
Enum(ReprOptions),
232233
Field,

src/librustc_privacy/lib.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
160160
self.prev_level
161161
}
162162
// Other `pub` items inherit levels from parents
163-
_ => {
163+
hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) |
164+
hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
165+
hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
166+
hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
164167
if item.vis == hir::Public { self.prev_level } else { None }
165168
}
166169
};
@@ -212,7 +215,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
212215
}
213216
}
214217
}
215-
_ => {}
218+
hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
219+
hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
220+
hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemDefaultImpl(..) => {}
216221
}
217222

218223
// Mark all items in interfaces of reachable items as reachable
@@ -225,6 +230,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
225230
hir::ItemUse(..) => {}
226231
// The interface is empty
227232
hir::ItemDefaultImpl(..) => {}
233+
// The interface is empty
234+
hir::ItemGlobalAsm(..) => {}
228235
// Visit everything
229236
hir::ItemConst(..) | hir::ItemStatic(..) |
230237
hir::ItemFn(..) | hir::ItemTy(..) => {
@@ -1092,6 +1099,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
10921099
hir::ItemMod(..) => {}
10931100
// Checked in resolve
10941101
hir::ItemUse(..) => {}
1102+
// No subitems
1103+
hir::ItemGlobalAsm(..) => {}
10951104
// Subitems of these items have inherited publicity
10961105
hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
10971106
hir::ItemTy(..) => {

src/librustc_resolve/build_reduced_graph.rs

+2
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ impl<'a> Resolver<'a> {
268268
self.define(parent, ident, TypeNS, imported_binding);
269269
}
270270

271+
ItemKind::GlobalAsm(..) => {}
272+
271273
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
272274

273275
ItemKind::Mod(..) => {

src/librustc_resolve/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,7 @@ impl<'a> Resolver<'a> {
17071707
}
17081708
}
17091709

1710-
ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) => {
1710+
ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_)=> {
17111711
// do nothing, these are just around to be encoded
17121712
}
17131713

src/librustc_save_analysis/dump_visitor.rs

+1
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
341341
Def::AssociatedTy(..) |
342342
Def::AssociatedConst(..) |
343343
Def::PrimTy(_) |
344+
Def::GlobalAsm(_) |
344345
Def::Err => {
345346
span_bug!(span,
346347
"process_def_kind for unexpected item: {:?}",

src/librustc_save_analysis/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
701701
Def::SelfTy(..) |
702702
Def::Label(..) |
703703
Def::Macro(..) |
704+
Def::GlobalAsm(..) |
704705
Def::Err => None,
705706
}
706707
}

src/librustc_trans/asm.rs

+8
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,11 @@ pub fn trans_inline_asm<'a, 'tcx>(
124124
llvm::LLVMMDNodeInContext(bcx.ccx.llcx(), &val, 1));
125125
}
126126
}
127+
128+
pub fn trans_global_asm<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
129+
ga: &hir::GlobalAsm) {
130+
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
131+
unsafe {
132+
llvm::LLVMRustAppendModuleInlineAsm(ccx.llmod(), asm.as_ptr());
133+
}
134+
}

0 commit comments

Comments
 (0)