1111
1212use std:: ffi:: CString ;
1313
14- use rustc:: hir:: CodegenFnAttrFlags ;
14+ use rustc:: hir:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
1515use rustc:: hir:: def_id:: { DefId , LOCAL_CRATE } ;
1616use rustc:: session:: Session ;
1717use rustc:: session:: config:: Sanitizer ;
@@ -134,11 +134,37 @@ pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
134134
135135/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
136136/// attributes.
137- pub fn from_fn_attrs ( cx : & CodegenCx < ' ll , ' _ > , llfn : & ' ll Value , id : DefId ) {
138- let codegen_fn_attrs = cx. tcx . codegen_fn_attrs ( id) ;
137+ pub fn from_fn_attrs (
138+ cx : & CodegenCx < ' ll , ' _ > ,
139+ llfn : & ' ll Value ,
140+ id : Option < DefId > ,
141+ ) {
142+ let codegen_fn_attrs = id. map ( |id| cx. tcx . codegen_fn_attrs ( id) )
143+ . unwrap_or ( CodegenFnAttrs :: new ( ) ) ;
139144
140145 inline ( llfn, codegen_fn_attrs. inline ) ;
141146
147+ // The `uwtable` attribute according to LLVM is:
148+ //
149+ // This attribute indicates that the ABI being targeted requires that an
150+ // unwind table entry be produced for this function even if we can show
151+ // that no exceptions passes by it. This is normally the case for the
152+ // ELF x86-64 abi, but it can be disabled for some compilation units.
153+ //
154+ // Typically when we're compiling with `-C panic=abort` (which implies this
155+ // `no_landing_pads` check) we don't need `uwtable` because we can't
156+ // generate any exceptions! On Windows, however, exceptions include other
157+ // events such as illegal instructions, segfaults, etc. This means that on
158+ // Windows we end up still needing the `uwtable` attribute even if the `-C
159+ // panic=abort` flag is passed.
160+ //
161+ // You can also find more info on why Windows is whitelisted here in:
162+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
163+ if !cx. sess ( ) . no_landing_pads ( ) ||
164+ cx. sess ( ) . target . target . options . requires_uwtable {
165+ attributes:: emit_uwtable ( llfn, true ) ;
166+ }
167+
142168 set_frame_pointer_elimination ( cx, llfn) ;
143169 set_probestack ( cx, llfn) ;
144170
@@ -162,7 +188,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) {
162188 // *in Rust code* may unwind. Foreign items like `extern "C" {
163189 // fn foo(); }` are assumed not to unwind **unless** they have
164190 // a `#[unwind]` attribute.
165- } else if !cx. tcx . is_foreign_item ( id) {
191+ } else if id . map ( |id| !cx. tcx . is_foreign_item ( id) ) . unwrap_or ( false ) {
166192 Some ( true )
167193 } else {
168194 None
@@ -208,14 +234,16 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) {
208234 // Note that currently the `wasm-import-module` doesn't do anything, but
209235 // eventually LLVM 7 should read this and ferry the appropriate import
210236 // module to the output file.
211- if cx. tcx . sess . target . target . arch == "wasm32" {
212- if let Some ( module) = wasm_import_module ( cx. tcx , id) {
213- llvm:: AddFunctionAttrStringValue (
214- llfn,
215- llvm:: AttributePlace :: Function ,
216- const_cstr ! ( "wasm-import-module" ) ,
217- & module,
218- ) ;
237+ if let Some ( id) = id {
238+ if cx. tcx . sess . target . target . arch == "wasm32" {
239+ if let Some ( module) = wasm_import_module ( cx. tcx , id) {
240+ llvm:: AddFunctionAttrStringValue (
241+ llfn,
242+ llvm:: AttributePlace :: Function ,
243+ const_cstr ! ( "wasm-import-module" ) ,
244+ & module,
245+ ) ;
246+ }
219247 }
220248 }
221249}
0 commit comments