[eddyb] rustc_codegen_ssa: handle LLVM unsafety correctly.
This commit is contained in:
parent
bf7f8cd3fc
commit
9bb6663431
7 changed files with 29 additions and 22 deletions
|
@ -84,8 +84,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
|
let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
|
||||||
let constraint_cstr = CString::new(all_constraints).unwrap();
|
let constraint_cstr = CString::new(all_constraints).unwrap();
|
||||||
let r = self.inline_asm_call(
|
let r = self.inline_asm_call(
|
||||||
asm.as_ptr(),
|
&asm,
|
||||||
constraint_cstr.as_ptr(),
|
&constraint_cstr,
|
||||||
&inputs,
|
&inputs,
|
||||||
output_type,
|
output_type,
|
||||||
ia.volatile,
|
ia.volatile,
|
||||||
|
|
|
@ -194,7 +194,9 @@ pub fn compile_codegen_unit<'ll, 'tcx>(tcx: TyCtxt<'ll, 'tcx, 'tcx>,
|
||||||
|
|
||||||
// Run replace-all-uses-with for statics that need it
|
// Run replace-all-uses-with for statics that need it
|
||||||
for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
|
for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
|
||||||
cx.static_replace_all_uses(old_g, new_g)
|
unsafe {
|
||||||
|
cx.static_replace_all_uses(old_g, new_g)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the llvm.used variable
|
// Create the llvm.used variable
|
||||||
|
|
|
@ -28,6 +28,7 @@ use rustc_codegen_ssa::base::to_immediate;
|
||||||
use rustc_codegen_ssa::mir::operand::{OperandValue, OperandRef};
|
use rustc_codegen_ssa::mir::operand::{OperandValue, OperandRef};
|
||||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::ffi::CStr;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
|
@ -838,7 +839,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inline_asm_call(&mut self, asm: *const c_char, cons: *const c_char,
|
fn inline_asm_call(&mut self, asm: &CStr, cons: &CStr,
|
||||||
inputs: &[&'ll Value], output: &'ll Type,
|
inputs: &[&'ll Value], output: &'ll Type,
|
||||||
volatile: bool, alignstack: bool,
|
volatile: bool, alignstack: bool,
|
||||||
dia: syntax::ast::AsmDialect) -> Option<&'ll Value> {
|
dia: syntax::ast::AsmDialect) -> Option<&'ll Value> {
|
||||||
|
@ -858,11 +859,17 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
let fty = self.cx().type_func(&argtys[..], output);
|
let fty = self.cx().type_func(&argtys[..], output);
|
||||||
unsafe {
|
unsafe {
|
||||||
// Ask LLVM to verify that the constraints are well-formed.
|
// Ask LLVM to verify that the constraints are well-formed.
|
||||||
let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons);
|
let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr());
|
||||||
debug!("Constraint verification result: {:?}", constraints_ok);
|
debug!("Constraint verification result: {:?}", constraints_ok);
|
||||||
if constraints_ok {
|
if constraints_ok {
|
||||||
let v = llvm::LLVMRustInlineAsm(
|
let v = llvm::LLVMRustInlineAsm(
|
||||||
fty, asm, cons, volatile, alignstack, AsmDialect::from_generic(dia));
|
fty,
|
||||||
|
asm.as_ptr(),
|
||||||
|
cons.as_ptr(),
|
||||||
|
volatile,
|
||||||
|
alignstack,
|
||||||
|
AsmDialect::from_generic(dia),
|
||||||
|
);
|
||||||
Some(self.call(v, inputs, None))
|
Some(self.call(v, inputs, None))
|
||||||
} else {
|
} else {
|
||||||
// LLVM has detected an issue with our constraints, bail out
|
// LLVM has detected an issue with our constraints, bail out
|
||||||
|
@ -1400,10 +1407,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
self.cx
|
self.cx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_basic_block(&mut self, bb: &'ll BasicBlock) {
|
unsafe fn delete_basic_block(&mut self, bb: &'ll BasicBlock) {
|
||||||
unsafe {
|
llvm::LLVMDeleteBasicBlock(bb);
|
||||||
llvm::LLVMDeleteBasicBlock(bb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_not_inline(&mut self, llret: &'ll Value) {
|
fn do_not_inline(&mut self, llret: &'ll Value) {
|
||||||
|
|
|
@ -498,11 +498,9 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn static_replace_all_uses(&self, old_g: &'ll Value, new_g: &'ll Value) {
|
unsafe fn static_replace_all_uses(&self, old_g: &'ll Value, new_g: &'ll Value) {
|
||||||
unsafe {
|
let bitcast = llvm::LLVMConstPointerCast(new_g, self.val_ty(old_g));
|
||||||
let bitcast = llvm::LLVMConstPointerCast(new_g, self.val_ty(old_g));
|
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
||||||
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
llvm::LLVMDeleteGlobal(old_g);
|
||||||
llvm::LLVMDeleteGlobal(old_g);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use super::intrinsic::IntrinsicCallMethods;
|
||||||
use super::type_::ArgTypeMethods;
|
use super::type_::ArgTypeMethods;
|
||||||
use super::HasCodegen;
|
use super::HasCodegen;
|
||||||
use common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope};
|
use common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope};
|
||||||
use libc::c_char;
|
use std::ffi::CStr;
|
||||||
use mir::operand::OperandRef;
|
use mir::operand::OperandRef;
|
||||||
use mir::place::PlaceRef;
|
use mir::place::PlaceRef;
|
||||||
use rustc::ty::layout::{Align, Size};
|
use rustc::ty::layout::{Align, Size};
|
||||||
|
@ -162,8 +162,8 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
|
||||||
) -> Self::Value;
|
) -> Self::Value;
|
||||||
fn inline_asm_call(
|
fn inline_asm_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
asm: *const c_char,
|
asm: &CStr,
|
||||||
cons: *const c_char,
|
cons: &CStr,
|
||||||
inputs: &[Self::Value],
|
inputs: &[Self::Value],
|
||||||
output: Self::Type,
|
output: Self::Type,
|
||||||
volatile: bool,
|
volatile: bool,
|
||||||
|
@ -318,6 +318,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
|
||||||
) -> Self::Value;
|
) -> Self::Value;
|
||||||
fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
|
fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
|
||||||
|
|
||||||
fn delete_basic_block(&mut self, bb: Self::BasicBlock);
|
unsafe fn delete_basic_block(&mut self, bb: Self::BasicBlock);
|
||||||
fn do_not_inline(&mut self, llret: Self::Value);
|
fn do_not_inline(&mut self, llret: Self::Value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,5 @@ pub trait StaticMethods<'tcx>: Backend<'tcx> {
|
||||||
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
|
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
|
||||||
fn get_static(&self, def_id: DefId) -> Self::Value;
|
fn get_static(&self, def_id: DefId) -> Self::Value;
|
||||||
fn codegen_static(&self, def_id: DefId, is_mutable: bool);
|
fn codegen_static(&self, def_id: DefId, is_mutable: bool);
|
||||||
fn static_replace_all_uses(&self, old_g: Self::Value, new_g: Self::Value);
|
unsafe fn static_replace_all_uses(&self, old_g: Self::Value, new_g: Self::Value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,7 +359,9 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
// Unreachable block
|
// Unreachable block
|
||||||
if !visited.contains(bb.index()) {
|
if !visited.contains(bb.index()) {
|
||||||
debug!("codegen_mir: block {:?} was not visited", bb);
|
debug!("codegen_mir: block {:?} was not visited", bb);
|
||||||
bx.delete_basic_block(fx.blocks[bb]);
|
unsafe {
|
||||||
|
bx.delete_basic_block(fx.blocks[bb]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue