about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm
diff options
context:
space:
mode:
authorMichael Bradshaw <mjbshaw@google.com>2018-09-29 19:51:09 -0700
committerMichael Bradshaw <mjbshaw@google.com>2018-09-29 19:51:09 -0700
commit43cc32fbb2506eff0090e894c1e8a46b62a8eb0b (patch)
treeac301fe1be819c25d833880da0ab32bf550016eb /src/librustc_codegen_llvm
parentaec5330082a0c4664abf0f6604c1b05768a90234 (diff)
parent9653f790333d1270f36f1614e85d8a7b54193e75 (diff)
downloadrust-43cc32fbb2506eff0090e894c1e8a46b62a8eb0b.tar.gz
rust-43cc32fbb2506eff0090e894c1e8a46b62a8eb0b.zip
Merge branch 'master' into drop
Diffstat (limited to 'src/librustc_codegen_llvm')
-rw-r--r--src/librustc_codegen_llvm/asm.rs8
-rw-r--r--src/librustc_codegen_llvm/back/link.rs12
-rw-r--r--src/librustc_codegen_llvm/back/write.rs2
-rw-r--r--src/librustc_codegen_llvm/builder.rs16
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs2
-rw-r--r--src/librustc_codegen_llvm/declare.rs4
-rw-r--r--src/librustc_codegen_llvm/diagnostics.rs22
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs6
-rw-r--r--src/librustc_codegen_llvm/mir/block.rs48
-rw-r--r--src/librustc_codegen_llvm/mir/place.rs9
-rw-r--r--src/librustc_codegen_llvm/mir/rvalue.rs2
-rw-r--r--src/librustc_codegen_llvm/mir/statement.rs6
12 files changed, 62 insertions, 75 deletions
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index 5d27f8eab3e..f1bb41bceba 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -30,7 +30,7 @@ pub fn codegen_inline_asm(
     ia: &hir::InlineAsm,
     outputs: Vec<PlaceRef<'ll, 'tcx>>,
     mut inputs: Vec<&'ll Value>
-) {
+) -> bool {
     let mut ext_constraints = vec![];
     let mut output_types = vec![];
 
@@ -97,6 +97,10 @@ pub fn codegen_inline_asm(
         ia.alignstack,
         dialect
     );
+    if r.is_none() {
+        return false;
+    }
+    let r = r.unwrap();
 
     // Again, based on how many outputs we have
     let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
@@ -117,6 +121,8 @@ pub fn codegen_inline_asm(
         llvm::LLVMSetMetadata(r, kind,
             llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
     }
+
+    return true;
 }
 
 pub fn codegen_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index 8248385c127..ce52fe00b0e 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -47,7 +47,8 @@ use std::str;
 use syntax::attr;
 
 pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
-                                  invalid_output_for_target, out_filename, check_file_is_writeable};
+                                  invalid_output_for_target, out_filename, check_file_is_writeable,
+                                  filename_for_metadata};
 
 // The third parameter is for env vars, used on windows to set up the
 // path for MSVC to find its DLLs, and gcc to find its bundled
@@ -218,15 +219,6 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
     false
 }
 
-fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf {
-    let out_filename = outputs.single_output_file.clone()
-        .unwrap_or(outputs
-            .out_directory
-            .join(&format!("lib{}{}.rmeta", crate_name, sess.opts.cg.extra_filename)));
-    check_file_is_writeable(&out_filename, sess);
-    out_filename
-}
-
 pub(crate) fn each_linked_rlib(sess: &Session,
                                info: &CrateInfo,
                                f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> {
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 447b505e79c..02ef690b942 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -196,6 +196,7 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
     let features = CString::new(features).unwrap();
     let is_pie_binary = !find_features && is_pie_binary(sess);
     let trap_unreachable = sess.target.target.options.trap_unreachable;
+    let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
 
     let asm_comments = sess.asm_comments();
 
@@ -213,6 +214,7 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
                 trap_unreachable,
                 singlethread,
                 asm_comments,
+                emit_stack_size_section,
             )
         };
 
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index e3526a5a2ee..77de88997e4 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -737,7 +737,7 @@ impl Builder<'a, 'll, 'tcx> {
     pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
                          inputs: &[&'ll Value], output: &'ll Type,
                          volatile: bool, alignstack: bool,
-                         dia: AsmDialect) -> &'ll Value {
+                         dia: AsmDialect) -> Option<&'ll Value> {
         self.count_insn("inlineasm");
 
         let volatile = if volatile { llvm::True }
@@ -753,9 +753,17 @@ impl Builder<'a, 'll, 'tcx> {
         debug!("Asm Output Type: {:?}", output);
         let fty = Type::func(&argtys[..], output);
         unsafe {
-            let v = llvm::LLVMRustInlineAsm(
-                fty, asm, cons, volatile, alignstack, dia);
-            self.call(v, inputs, None)
+            // Ask LLVM to verify that the constraints are well-formed.
+            let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons);
+            debug!("Constraint verification result: {:?}", constraints_ok);
+            if constraints_ok == llvm::True {
+                let v = llvm::LLVMRustInlineAsm(
+                    fty, asm, cons, volatile, alignstack, dia);
+                Some(self.call(v, inputs, None))
+            } else {
+                // LLVM has detected an issue with our constaints, bail out
+                None
+            }
         }
     }
 
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 7b0c413e857..99919a940b4 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -279,7 +279,7 @@ pub fn create_function_debug_context(
         }
         None => {}
     };
-    if cx.layout_of(sig.output()).abi.is_uninhabited() {
+    if cx.layout_of(sig.output()).abi == ty::layout::Abi::Uninhabited {
         flags = flags | DIFlags::FlagNoReturn;
     }
 
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index 7141c9ece89..5e743ac51bc 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -23,7 +23,7 @@
 use llvm;
 use llvm::AttributePlace::Function;
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::LayoutOf;
+use rustc::ty::layout::{self, LayoutOf};
 use rustc::session::config::Sanitizer;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_target::spec::PanicStrategy;
@@ -137,7 +137,7 @@ pub fn declare_fn(
     let fty = FnType::new(cx, sig, &[]);
     let llfn = declare_raw_fn(cx, name, fty.llvm_cconv(), fty.llvm_type(cx));
 
-    if cx.layout_of(sig.output()).abi.is_uninhabited() {
+    if cx.layout_of(sig.output()).abi == layout::Abi::Uninhabited {
         llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
     }
 
diff --git a/src/librustc_codegen_llvm/diagnostics.rs b/src/librustc_codegen_llvm/diagnostics.rs
index 94776f17c79..242b7a1a119 100644
--- a/src/librustc_codegen_llvm/diagnostics.rs
+++ b/src/librustc_codegen_llvm/diagnostics.rs
@@ -47,4 +47,26 @@ unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok!
 ```
 "##,
 
+E0668: r##"
+Malformed inline assembly rejected by LLVM.
+
+LLVM checks the validity of the constraints and the assembly string passed to
+it. This error implies that LLVM seems something wrong with the inline
+assembly call.
+
+In particular, it can happen if you forgot the closing bracket of a register
+constraint (see issue #51430):
+```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
+#![feature(asm)]
+
+fn main() {
+    let rax: u64;
+    unsafe {
+        asm!("" :"={rax"(rax));
+        println!("Accumulator is: {}", rax);
+    }
+}
+```
+"##,
+
 }
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index a5f4137c62b..8485db4210c 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -1208,6 +1208,9 @@ extern "C" {
                              AlignStack: Bool,
                              Dialect: AsmDialect)
                              -> &Value;
+    pub fn LLVMRustInlineAsmVerify(Ty: &Type,
+                             Constraints: *const c_char)
+                             -> Bool;
 
     pub fn LLVMRustDebugMetadataVersion() -> u32;
     pub fn LLVMRustVersionMajor() -> u32;
@@ -1460,7 +1463,8 @@ extern "C" {
                                        DataSections: bool,
                                        TrapUnreachable: bool,
                                        Singlethread: bool,
-                                       AsmComments: bool)
+                                       AsmComments: bool,
+                                       EmitStackSizeSection: bool)
                                        -> Option<&'static mut TargetMachine>;
     pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
     pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module);
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs
index 709fceb4925..a534b4e478f 100644
--- a/src/librustc_codegen_llvm/mir/block.rs
+++ b/src/librustc_codegen_llvm/mir/block.rs
@@ -482,54 +482,6 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     _ => FnType::new(bx.cx, sig, &extra_args)
                 };
 
-                // emit a panic instead of instantiating an uninhabited type
-                if (intrinsic == Some("init") || intrinsic == Some("uninit")) &&
-                    fn_ty.ret.layout.abi.is_uninhabited()
-                {
-                    let loc = bx.sess().source_map().lookup_char_pos(span.lo());
-                    let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
-                    let filename = C_str_slice(bx.cx, filename);
-                    let line = C_u32(bx.cx, loc.line as u32);
-                    let col = C_u32(bx.cx, loc.col.to_usize() as u32 + 1);
-                    let align = tcx.data_layout.aggregate_align
-                        .max(tcx.data_layout.i32_align)
-                        .max(tcx.data_layout.pointer_align);
-
-                    let str = format!(
-                        "Attempted to instantiate uninhabited type {} using mem::{}",
-                        sig.output(),
-                        if intrinsic == Some("init") { "zeroed" } else { "uninitialized" }
-                    );
-                    let msg_str = Symbol::intern(&str).as_str();
-                    let msg_str = C_str_slice(bx.cx, msg_str);
-                    let msg_file_line_col = C_struct(bx.cx,
-                                                    &[msg_str, filename, line, col],
-                                                    false);
-                    let msg_file_line_col = consts::addr_of(bx.cx,
-                                                            msg_file_line_col,
-                                                            align,
-                                                            Some("panic_loc"));
-
-                    // Obtain the panic entry point.
-                    let def_id =
-                        common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
-                    let instance = ty::Instance::mono(bx.tcx(), def_id);
-                    let fn_ty = FnType::of_instance(bx.cx, &instance);
-                    let llfn = callee::get_fn(bx.cx, instance);
-
-                    // Codegen the actual panic invoke/call.
-                    do_call(
-                        self,
-                        bx,
-                        fn_ty,
-                        llfn,
-                        &[msg_file_line_col],
-                        destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
-                        cleanup,
-                    );
-                    return;
-                }
-
                 // The arguments we'll be passing. Plus one to account for outptr, if used.
                 let arg_count = fn_ty.args.len() + fn_ty.ret.is_indirect() as usize;
                 let mut llargs = Vec::with_capacity(arg_count);
diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs
index bc6ebd360e8..c781b456af6 100644
--- a/src/librustc_codegen_llvm/mir/place.rs
+++ b/src/librustc_codegen_llvm/mir/place.rs
@@ -173,10 +173,7 @@ impl PlaceRef<'ll, 'tcx> {
         let cx = bx.cx;
         let field = self.layout.field(cx, ix);
         let offset = self.layout.fields.offset(ix);
-        let effective_field_align = self.align
-            .min(self.layout.align)
-            .min(field.align)
-            .restrict_for_offset(offset);
+        let effective_field_align = self.align.restrict_for_offset(offset);
 
         let simple = || {
             // Unions and newtypes only use an offset of 0.
@@ -278,7 +275,7 @@ impl PlaceRef<'ll, 'tcx> {
     /// Obtain the actual discriminant of a value.
     pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value {
         let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
-        if self.layout.abi.is_uninhabited() {
+        if self.layout.abi == layout::Abi::Uninhabited {
             return C_undef(cast_to);
         }
         match self.layout.variants {
@@ -341,7 +338,7 @@ impl PlaceRef<'ll, 'tcx> {
     /// Set the discriminant for a new value of the given case of the given
     /// representation.
     pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) {
-        if self.layout.for_variant(bx.cx, variant_index).abi.is_uninhabited() {
+        if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
             return;
         }
         match self.layout.variants {
diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs
index fa22bdff94d..c3ec347f608 100644
--- a/src/librustc_codegen_llvm/mir/rvalue.rs
+++ b/src/librustc_codegen_llvm/mir/rvalue.rs
@@ -290,7 +290,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     mir::CastKind::Misc => {
                         assert!(cast.is_llvm_immediate());
                         let ll_t_out = cast.immediate_llvm_type(bx.cx);
-                        if operand.layout.abi.is_uninhabited() {
+                        if operand.layout.abi == layout::Abi::Uninhabited {
                             return (bx, OperandRef {
                                 val: OperandValue::Immediate(C_undef(ll_t_out)),
                                 layout: cast,
diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs
index b4eb7615f98..6bd41bfe16f 100644
--- a/src/librustc_codegen_llvm/mir/statement.rs
+++ b/src/librustc_codegen_llvm/mir/statement.rs
@@ -86,7 +86,11 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     self.codegen_operand(&bx, input).immediate()
                 }).collect();
 
-                asm::codegen_inline_asm(&bx, asm, outputs, input_vals);
+                let res = asm::codegen_inline_asm(&bx, asm, outputs, input_vals);
+                if !res {
+                    span_err!(bx.sess(), statement.source_info.span, E0668,
+                              "malformed inline assembly");
+                }
                 bx
             }
             mir::StatementKind::FakeRead(..) |