Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upImplement Win64 eh_personality natively. #27210
Conversation
rust-highfive
assigned
brson
Jul 22, 2015
This comment has been minimized.
This comment has been minimized.
|
r? @brson (rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
|
I am not quite happy about the way |
rust-highfive
assigned
alexcrichton
and unassigned
brson
Jul 22, 2015
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
nagisa
reviewed
Jul 22, 2015
| [libstd implementation](../std/rt/unwind/index.html) for more | ||
| The second and third of these functions, `eh_personality` and `rust_eh_unwind_resume`, | ||
| are used by the failure mechanisms of the compiler. These are often mapped to GCC's | ||
| personality function and libgcc's `_Unwind_Resume` respectively |
This comment has been minimized.
This comment has been minimized.
nagisa
Jul 22, 2015
Contributor
Wording of this sentence somehow seems to suggest GCC personality function and _Unwind_Resume come from two different locations, while in practice they both come from libgcc.
nagisa
reviewed
Jul 22, 2015
| @@ -512,6 +517,13 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, | |||
| None => {}, | |||
| } | |||
|
|
|||
| // Inject a local-scoped `_Unwind_Resume` function, which redirects to `rust_eh_unwind_resume`. | |||
| // This must be done after optimizations, because until DwarfEHPrepare pass has been run, | |||
| // `_Unwind_Resume` is not referenced by any live code and would have been eliminated by opt. | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
This may also be able to prevent elimination through the llvm.used global
alexcrichton
reviewed
Jul 22, 2015
| @@ -38,6 +38,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { | |||
| // provided by libstd. | |||
| #[lang = "stack_exhausted"] extern fn stack_exhausted() {} | |||
| #[lang = "eh_personality"] extern fn eh_personality() {} | |||
| #[no_mangle] pub extern fn rust_eh_unwind_resume() {} | |||
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
It looks like this only needs to be defined on 64-bit windows targets, so can this be omitted? I suspect 99% of #![no_std] users aren't working on Windows.
This comment has been minimized.
This comment has been minimized.
vadimcn
Jul 23, 2015
Author
Contributor
Without it doctests fail on Windows. Also, if we ever drop libgcc on other platforms, we'll need it.
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Jul 22, 2015
| @@ -16,6 +16,7 @@ pub fn target() -> Target { | |||
| // On Win64 unwinding is handled by the OS, so we can link libgcc statically. | |||
| base.pre_link_args.push("-static-libgcc".to_string()); | |||
| base.pre_link_args.push("-m64".to_string()); | |||
| base.custom_unwind_resume = true; | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Jul 22, 2015
| } | ||
|
|
||
| #[inline(never)] | ||
| pub unsafe fn find_landing_pad(lsda: *const u8, context: EHContext) -> Option<usize> { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
A few notes on this function:
- Is there public documentation available for this protocol? I'd love to reference this against a known implementation or description to verify it, but also so we can understand what this is doing months from now.
- Can you document why this is
inline(never)?
This comment has been minimized.
This comment has been minimized.
vadimcn
Jul 23, 2015
Author
Contributor
Is there public documentation available for this protocol?
Not really. Gcc LSDA format is defined by, well, gcc implementation. Aside from that, there are a few blog posts... I'll link them here.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 23, 2015
Member
Yeah as many links as possible would be nice, even if they're just links to code in other repos. Surely this implementation came from somewhere, and it'd be good to have a trail saying how so!
alexcrichton
reviewed
Jul 22, 2015
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| //! General DWARF format parsing utilities |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
Similarly as above, it'd be great to have a lot more documentation on this module. For example the read_uleb128 function would be nice to have a hyperlink to the definition of the format, and some overall docs about what this module's doing would be nice.
This comment has been minimized.
This comment has been minimized.
vadimcn
Jul 23, 2015
Author
Contributor
Now these are defined in the DWARF standard. I'll add a section reference here.
alexcrichton
reviewed
Jul 22, 2015
| unsafe { | ||
| __gcc_personality_v0(version, actions, exception_class, ue_header, | ||
| context) | ||
| } |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
Oh hm ok I think I see what's going on here, it's because this is legit running in something other than the search phase, so we probably need to do something more than just returning a constant.
This comment has been minimized.
This comment has been minimized.
vadimcn
Jul 23, 2015
Author
Contributor
This is basically a roll-back of the rust_try_inner magic, which was created because of the way libgcc's C personality routine works on win64. I thought it'd be good to get rid of unneeded complications. This is the way this code used to be a year ago.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
vadimcn
Jul 23, 2015
Author
Contributor
I'll try to make the equivalent simplification in your trans_gnu_try.
alexcrichton
reviewed
Jul 22, 2015
| @@ -99,8 +92,6 @@ pub mod eabi { | |||
| } | |||
|
|
|||
| #[lang="eh_personality"] | |||
| #[no_mangle] // referenced from rust_try.ll | |||
| #[allow(private_no_mangle_fns)] | |||
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
Does this pass all the tests? I vaguely remember seeing the rust_eh_personality symbol in a list of reachable symbols which was necessary for LTO working, but I may be remembering incorrectly.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Jul 22, 2015
| @@ -47,6 +47,9 @@ pub mod args; | |||
| mod at_exit_imp; | |||
| mod libunwind; | |||
|
|
|||
| #[cfg(all(windows, target_arch="x86_64", target_env="gnu"))] | |||
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
It may be worth having this just be compiled for all platforms and it'll just end up being optimized away on most. That way we can catch breakage to it on all platforms instead of just 64-bit windows.
alexcrichton
reviewed
Jul 22, 2015
| // Since these assumptions do not generally hold true for foreign exceptions (system faults, | ||
| // C++ exceptions, etc), we make no attempt to invoke our landing pads (and, thus, destructors!) | ||
| // for anything other than RUST_PANICs. This is considered acceptable, because the behavior of | ||
| // throwing exceptions through a C ABI boundary is undefined. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
Could you format this to 80-chars wide? (what the rest of the runtime is formatted to)
alexcrichton
reviewed
Jul 22, 2015
|
|
||
| if er.ExceptionFlags & EXCEPTION_UNWIND == 0 { // we are in the dispatch phase | ||
| if er.ExceptionCode == RUST_PANIC { | ||
| if let Some(lpad) = find_landing_pad(dc) { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
This may be a bit clearer as:
let lpad = find_landing_pad(dc).unwrap_or_else(|| {
rtabort!(...)
});
alexcrichton
reviewed
Jul 22, 2015
|
|
||
| #[lang="eh_personality"] | ||
| #[cfg(not(test))] | ||
| unsafe extern "C" fn rust_eh_personality( |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
Is this just the same as rust_eh_personality_catch? These two functions look the same except for the expectation of the landing pad existing...
Overall I'd find it at least helpful to have a nice big doc comment at the top of the module explaining what's going on here. I have a little understanding of what mechanisms are in play, but I know why these are structured the way they are. For example it's not clear to my why the catch personality is catching but this one isn't?
This comment has been minimized.
This comment has been minimized.
vadimcn
Jul 23, 2015
Author
Contributor
Is this just the same as rust_eh_personality_catch? These two functions look the same except for the expectation of the landing pad existing...
Yes, that the only difference at the moment. There used to be more when I tried to support running destructors on foreign exceptions.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 23, 2015
Member
Interesting... I guess this shows how little I know about the ABI of these exceptions on windows! I guess whether a landing pad is a "catch" landing pad is encoded in the landing pad itself and not the personality function?
Overall it basically may mean that we can merge these two functions and only have one?
alexcrichton
reviewed
Jul 22, 2015
| ExceptionContinueSearch | ||
| } | ||
|
|
||
| #[no_mangle] // referenced from landing pads |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 22, 2015
Member
Can you expand this to a comment explaining what this function is doing? It'd be nice to mention that this is called from all landing pads and is injected by LLVM, and it's also why it's pub + #[no_mangle].
Also, can you remove the "C" part from the header?
This comment has been minimized.
This comment has been minimized.
|
Nice work @vadimcn! |
liigo
reviewed
Jul 23, 2015
| // [24:27] = type | ||
| // [0:23] = magic | ||
| const ETYPE: DWORD = 0b1110_u32 << 28; | ||
| const MAGIC: DWORD = 0x525354; // "RST" |
This comment has been minimized.
This comment has been minimized.
liigo
Jul 23, 2015
Contributor
RST also refers to reStructuredText. How about we use .rs here?
const MAGIC: DWORD = 0x2e7273; // ".rs"
brson
added
the
relnotes
label
Jul 23, 2015
This comment has been minimized.
This comment has been minimized.
|
Epic patch. |
vadimcn
force-pushed the
vadimcn:win64-eh-pers
branch
2 times, most recently
from
502a189
to
59d5b19
Jul 24, 2015
This comment has been minimized.
This comment has been minimized.
|
Addressed comments and rebased on top of master. r? |
vadimcn
force-pushed the
vadimcn:win64-eh-pers
branch
from
59d5b19
to
63049c7
Jul 24, 2015
alexcrichton
reviewed
Jul 24, 2015
| pub mod imp; | ||
| #[cfg(not(target_env = "msvc"))] #[path = "gcc.rs"] #[doc(hidden)] | ||
|
|
||
| // x86-pc-windows-gnu and all others |
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Jul 24, 2015
| // `_Unwind_Resume` routine. To avoid confusion with the same symbol exported | ||
| // from libgcc, we redirect it to `rust_eh_unwind_resume`. | ||
| // Since resolution of this symbol is done by the linker, `rust_eh_unwind_resume` | ||
| // must be marked `pub` + `#[no_mangle]`. (Can we make it a lang item?) |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 24, 2015
Member
Unfortunately I don't think this can be a lang item because libraries like libcore/libcollections need to reference this (they're generating landing pads) so it needs to have a well known symbol name (e.g. it's used before it's defined).
This comment has been minimized.
This comment has been minimized.
|
Works now. r? |
This comment has been minimized.
This comment has been minimized.
|
@bors: r+ |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Aug 2, 2015
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
Seems legit:
On Sun, Aug 2, 2015 at 12:08 PM, bors notifications@github.com wrote:
|
This comment has been minimized.
This comment has been minimized.
|
Fixed. Let's try again? |
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Aug 3, 2015
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@bors: retry On Mon, Aug 3, 2015 at 10:37 AM, bors notifications@github.com wrote:
|
bors
added a commit
that referenced
this pull request
Aug 3, 2015
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bors
merged commit 96d1db2
into
rust-lang:master
Aug 3, 2015
This comment has been minimized.
This comment has been minimized.
|
|
vadimcn commentedJul 22, 2015
After this change, the only remaining symbol we are pulling from libgcc on Win64 is
__chkstk_ms- the stack probing routine.