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

Tracking issue for global-asm support (RFC 1548) #35119

Open
nikomatsakis opened this issue Jul 29, 2016 · 30 comments
Open

Tracking issue for global-asm support (RFC 1548) #35119

nikomatsakis opened this issue Jul 29, 2016 · 30 comments

Comments

@nikomatsakis
Copy link
Contributor

@nikomatsakis nikomatsakis commented Jul 29, 2016

Tracking issue for global_asm! macro rust-lang/rfcs#1548:

Note that this is intended as a (particularly) experimental feature.

Feedback on its design is required, as well as comparisons with naked fns.

@jackpot51

This comment has been minimized.

Copy link
Contributor

@jackpot51 jackpot51 commented Jul 29, 2016

Don't take away naked functions!!!!!!!!!!!!!!!!!!!

They are a crucial component of building operating systems in Rust.

Without naked functions, it is impossible to do context switching without moving huge amounts of code into assembler. Converting such code to global_asm! is unnecessary, insecure, difficult to read and modify, and requires repeating code for each target.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor Author

@nikomatsakis nikomatsakis commented Jul 29, 2016

@jackpot51 more detailed examples would be great :)

@nikomatsakis

This comment has been minimized.

Copy link
Contributor Author

@nikomatsakis nikomatsakis commented Jul 29, 2016

@jackpot51 but rest easy, I don't think we're in any hurry to make firm decisions here. :)

@ticki

This comment has been minimized.

Copy link
Contributor

@ticki ticki commented Jul 29, 2016

@nikomatsakis They're used in anything from interrupt handler to context switches. I would cry for 10 years straight if you removed them.

@steveklabnik

This comment has been minimized.

Copy link
Member

@steveklabnik steveklabnik commented Jul 29, 2016

To make this concrete, here is a PR where I went from regular old asm to naked fn: https://github.com/intermezzOS/kernel/pull/49/files

All that setup code in src/src/asm/interrupt_handlers.asm was able to go away; the duplication between the extern declarations in src/interrupts/src/lib.rs was able to go away... much, much, much nicer.

@jackpot51

This comment has been minimized.

Copy link
Contributor

@jackpot51 jackpot51 commented Jul 29, 2016

Thanks @steveklabnik for showing the potential of #[naked]. Our experience in Redox was similar

@parched

This comment has been minimized.

Copy link
Contributor

@parched parched commented Jul 29, 2016

Regarding having compile time constants and unmangled labels in it, would it possible to have separate procedural macro that did this? Something like unmangle!(ident) and eval!(expr) that produced string literals. Or is that not possible?

If a general way like that wouldn't work then something like the way armcc does it would be good.

@nagisa

This comment has been minimized.

Copy link
Contributor

@nagisa nagisa commented Jul 29, 2016

I do not see how any naked function is not trivially convertible to a global_asm! or vice-versa, though (examples pointing out the contrary much appreciated). For example, you could have a naked! { fn peach() { /* asm goes here */ } which expands to global_asm! as an implementation of naked functions. Making global_asm! just a wrapper over naked functions seems also plausible to some extent.

Otherwise, I agree with Niko, that nobody is making any decisions anytime soon, but would like to add that seeing quality of naked function implementation, its future looks bleak.

@eternaleye

This comment has been minimized.

Copy link
Contributor

@eternaleye eternaleye commented Jul 29, 2016

@nagisa: I agree with you on naked-functions-on-top-of-global_asm!, but I actually disagree on the inverse.

In particular, it relies on doing awful Duff's Device-like tricks, where asm that's syntactically inside a function is treated semantically as if it was global.

If Rust ever grows a principled handling of inline asm, that sounds like an immense obstacle and/or footgun.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor Author

@nikomatsakis nikomatsakis commented Aug 2, 2016

On Fri, Jul 29, 2016 at 03:49:10PM -0700, eternaleye wrote:

@nagisa: I agree with you on naked-functions-over-global_asm, but I actually disagree on the inverse.

To clarify: do you mean "simulating global asm using a dummy naked function is a hack"?

@eternaleye

This comment has been minimized.

Copy link
Contributor

@eternaleye eternaleye commented Aug 2, 2016

@nikomatsakis

To clarify: do you mean "simulating global asm using a dummy naked function is a hack"?

In essence, yes - I feel using naked functions to simulate global asm is a hack, and one that could easily be broken by non-rustc parts of the compilation process to boot.

@whitequark whitequark mentioned this issue Aug 31, 2016
2 of 4 tasks complete
@whitequark

This comment has been minimized.

Copy link
Member

@whitequark whitequark commented Aug 31, 2016

I am in favor of this feature. My problem is that I need to use ARM EHABI directives inside assembly, however LLVM does not support them inside call asm instructions, and there is no workaround (specifically, .save must come after .fnstart but the context of call asm is as-if there was no .fnstart so it asserts in the parser; and I cannot specify .fnstart inside the call asm itself since it would break in a similar way after codegen then).

Of course, this is just one particular bug in LLVM (that I'm not going to fix, personally, I have better things to do). Even if it was fixed, however, I am sure there are other instances where assembly within a naked function does not behave in the same way as module-level assembly, and it would be unwise to assume that all problems related to those can be worked around. If they have to be fixed upstream, then there is at least a year of delay before the fix trickles down and the crate becomes usable on crates.io.

@mrhota

This comment has been minimized.

Copy link
Contributor

@mrhota mrhota commented Mar 13, 2017

btw, visitors from the future, I'm working on this.

bors added a commit that referenced this issue Apr 3, 2017
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
bors added a commit that referenced this issue Apr 5, 2017
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
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 5, 2017
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
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 6, 2017
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
bors added a commit that referenced this issue Apr 6, 2017
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
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 12, 2017
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
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 12, 2017
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
bors added a commit that referenced this issue Apr 12, 2017
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
bors added a commit that referenced this issue Apr 13, 2017
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
bors added a commit that referenced this issue Apr 13, 2017
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
bors added a commit that referenced this issue Apr 13, 2017
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
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 14, 2017
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
bors added a commit that referenced this issue Apr 14, 2017
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
@mrhota

This comment has been minimized.

Copy link
Contributor

@mrhota mrhota commented Feb 27, 2018

What needs to happen for this feature to become stable?

@cramertj

This comment has been minimized.

Copy link
Member

@cramertj cramertj commented Jun 25, 2018

@mrhota This is blocked on having any form of asm stable-- see discussion on #29722

@dvc94ch

This comment has been minimized.

Copy link
Contributor

@dvc94ch dvc94ch commented Aug 13, 2018

This is blocked on having any form of asm stable-- see discussion on #29722

@cramertj can you please explain? As I understand it the inline asm is unstable because the inline-asm-contraint-string may change at any time and is also llvm specific which would tie rust to the llvm backend. But I don't see the same issue with global_asm! since it should conform to the architecture's assembler manual and should be possible to implement with any backend.

cc @japaric

@japaric

This comment has been minimized.

Copy link
Member

@japaric japaric commented Aug 25, 2018

But I don't see the same issue with global_asm! since it should conform to the architecture's assembler manual

Does it though? It probably does when it comes to the actual instructions, but, for example, the global_asm! syntax (which assume is the same as LLVM's syntax) for ARM directives differs from what's specified in the ARM Compiler Toolchain Assembler Reference. In global_asm! and in gas (GNU assembler) I would write .global FOO whereas the ARM manual says I should write EXPORT FOO or GLOBAL FOO.

Apart from the syntax around directives I'm a bit concerned about directives letting you do stuff with symbols that you can't do in pure Rust. Setting the section name in global_asm! seems OK because it's equivalent to Rust's link_section attribute but directives also let you create weak symbols and weak aliases which is not possible to do in pure Rust. Should Rust catch up in terms of symbol manipulation before we stabilize global_asm!? If it doesn't people may rely more on global_asm! (which we don't have much control over since it's LLVM's code) than if it did and I'm not sure that's a good thing.

It might be worth to preprocess the global_asm! string and whitelist some directives and feature gate the others. Mostly to make sure we are not exposing unintended features (like .abort which gas considers as deprecated).

@parched

This comment has been minimized.

Copy link
Contributor

@parched parched commented Aug 26, 2018

@japaric

the global_asm! syntax (which assume is the same as LLVM's syntax) for ARM directives differs from what's specified in the ARM Compiler Toolchain Assembler Reference.

FWIW that's the old version of the Arm Compiler, version 6+ uses LLVM, so is the same as global_asm!

It might be worth to preprocess the global_asm!

Seems reasonable to me.

@dvc94ch

This comment has been minimized.

Copy link
Contributor

@dvc94ch dvc94ch commented Aug 26, 2018

For RISCV there is a wip assembler manual that the gcc and llvm backends intend to follow. Maybe we can enable it for architectures where this isn't a problem? 😇

@whitequark

This comment has been minimized.

Copy link
Member

@whitequark whitequark commented Aug 26, 2018

Maybe we can enable it for architectures where this isn't a problem?

I don't think you can do that, because (as I understand it) e.g. binutils as always recognizes certain extensions that are common to all platforms. So people could write code relying on those and it'll break on e.g. llvm as.

@japaric

This comment has been minimized.

Copy link
Member

@japaric japaric commented Aug 26, 2018

@dvc94ch there's no precedent for stable language features that only work when targeting certain architectures / platforms so it seems very unlikely that will happen.

@maccarro

This comment has been minimized.

Copy link

@maccarro maccarro commented Apr 17, 2019

What is blocking this feature from becoming stable? We're relying on this feature for OS development and would like to be moving towards using a stable toolchain.

@mark-i-m

This comment has been minimized.

Copy link
Member

@mark-i-m mark-i-m commented Apr 18, 2019

I might be wrong, but my impression is that we are leaning towards inline asm instead of this...

Personally, I find inline asm + naked fns to be a cleaner solution that composes better and is slightly more portable.

@mjbshaw

This comment has been minimized.

Copy link
Contributor

@mjbshaw mjbshaw commented Apr 18, 2019

I hope global_asm! doesn't get abandoned in favor of asm!. Unless asm! becomes a superset of global_asm! that supports stuff like .p2align, .ios_version_min, .cfi_*, custom GCC exception tables, etc.

@mark-i-m

This comment has been minimized.

Copy link
Member

@mark-i-m mark-i-m commented Apr 18, 2019

@mjbshaw I’m curious if you can give more details of your use case. It seems like the vast majority of use cases can be served by naked fns and inline assembly, where as global-asm is barely a step away from just using an assembler and linker manually.

What are the concrete advantages to using global-asm instead of writing a .S file and linking it with your program? Is it just convenience?

@mjbshaw

This comment has been minimized.

Copy link
Contributor

@mjbshaw mjbshaw commented Apr 18, 2019

@mark-i-m Convenience is my primary motivation. If rustc (and cargo) could consume assembly files without build.rs (much like how gcc and clang can consume assembly files) then I would find that to be convenient enough for my own needs.

But convenience aside, there's one issue with using external assembly files: you can't refer to private symbols in the Rust code anymore. For example:

global_asm! {r#"
  .section  __TEXT,__text,regular,pure_instructions
  .globl  _do_stuff_in_asm
_do_stuff_in_asm:
  # ... code that consumes L_SPECIAL_PRIVATE_SYMBOL ...
  retq

  .section	__TEXT,__special_section
L_SPECIAL_PRIVATE_SYMBOL:
	.asciz	"foo"
"#}

pub fn do_stuff_in_rust() -> &'static [u8; 4] {
  extern "C" {
    #[link_name = "\x01L_SPECIAL_PRIVATE_SYMBOL"]
    static foo: &'static [u8; 4];
  }
  return unsafe { foo };
}

In this example, both the Rust code and the global assembly can use L_SPECIAL_PRIVATE_SYMBOL. But if the global assembly is separated out into a separate assembly file, then the Rust code can no longer access L_SPECIAL_PRIVATE_SYMBOL (unless the symbol is made public instead of private, but that's not really desirable and sometimes isn't feasible depending on the platform and the symbol in question).

@mark-i-m

This comment has been minimized.

Copy link
Member

@mark-i-m mark-i-m commented Apr 18, 2019

@mark-i-m

This comment has been minimized.

Copy link
Member

@mark-i-m mark-i-m commented Apr 18, 2019

One other data point: I find myself still using a .S file and manually invoking the assembler and linker because I want to position certain sections of the binary at certain locations.

This gives me the idea of turning global asm into a new attribute:

#[cfg(target-arch=“x86-64”)]
#[asm(“arch/entry.S”, linker-args=“...”)]
@gz

This comment has been minimized.

Copy link

@gz gz commented Apr 18, 2019

FWIW passing .S files to rustc seems like a good way to go about it, without introducing language features/complexity for such (arguably niche) situations.

@GuillaumeDIDIER

This comment has been minimized.

Copy link

@GuillaumeDIDIER GuillaumeDIDIER commented Oct 25, 2019

Is there any difference between having global_asm! and having rustc able to eat .S files. I think the issues with either one are the same, and that supporting either or both is probably the same work.

(But I may be mistaken).

Consequently why not support both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.