Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add global_asm! for module-level inline assembly #1548

Merged
merged 1 commit into from
Jul 29, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions text/0000-global-asm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
- Feature Name: global_asm
- Start Date: 2016-03-18
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary

This RFC exposes LLVM's support for [module-level inline assembly](http://llvm.org/docs/LangRef.html#module-level-inline-assembly) by adding a `global_asm!` macro. The syntax is very simple: it just takes a string literal containing the assembly code.

Example:
```rust
global_asm!(r#"
.globl my_asm_func
my_asm_func:
ret
"#);

extern {
fn my_asm_func();
}
```

# Motivation
[motivation]: #motivation

There are two main use cases for this feature. The first is that it allows functions to be written completely in assembly, which mostly eliminates the need for a `naked` attribute. This is mainly useful for function that use a custom calling convention, such as interrupt handlers.

Another important use case is that it allows external assembly files to be used in a Rust module without needing hacks in the build system:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you detail what exact build system hacks are required currently to support external asm files?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need an external assembler. Where is it? Is it the right version? Does it support the target platform(s)? Does it output in the proper location? etc etc. All this makes for ugly build.rs boilerplate, and worse incremental rebuilds.

This aspect of the motivation is exactly the same as that for naked functions.


```rust
global_asm!(include_str!("my_asm_file.s"));
```

Assembly files can also be preprocessed or generated by `build.rs` (for example using the C preprocessor), which will produce output files in the Cargo output directory:

```rust
global_asm!(include_str!(concat!(env!("OUT_DIR"), "/preprocessed_asm.s")));
```

# Detailed design
[design]: #detailed-design

See description above, not much to add. The macro will map directly to LLVM's `module asm`.

# Drawbacks
[drawbacks]: #drawbacks

Like `asm!`, this feature depends on LLVM's integrated assembler.

# Alternatives
[alternatives]: #alternatives

The current way of including external assembly is to compile the assembly files using gcc in `build.rs` and link them into the Rust program as a static library.

An alternative for functions written entirely in assembly is to add a [`#[naked]` function attribute](https://github.com/rust-lang/rfcs/pull/1201).

# Unresolved questions
[unresolved]: #unresolved-questions

None