提交 249d5aca 编写于 作者: I Irina Popa

rustc_codegen_llvm: use safe references for Context and Module.

上级 af04e942
......@@ -20,8 +20,8 @@
use llvm::{self, False, True};
pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
let llcx = mods.llcx;
let llmod = mods.llmod;
let llcx = &*mods.llcx;
let llmod = mods.llmod();
let usize = match &tcx.sess.target.target.target_pointer_width[..] {
"16" => llvm::LLVMInt16TypeInContext(llcx),
"32" => llvm::LLVMInt32TypeInContext(llcx),
......
......@@ -30,8 +30,8 @@
use abi;
use back::link;
use back::write::{self, OngoingCodegen, create_target_machine};
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
use back::write::{self, OngoingCodegen};
use llvm::{ValueRef, Vector, get_param};
use llvm;
use metadata;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
......@@ -59,7 +59,7 @@
use rustc_mir::monomorphize::item::DefPathBasedNames;
use common::{self, C_struct_in_context, C_array, val_ty};
use consts;
use context::{self, CodegenCx};
use context::CodegenCx;
use debuginfo;
use declare;
use meth;
......@@ -77,7 +77,6 @@
use std::any::Any;
use std::ffi::CString;
use std::str;
use std::sync::Arc;
use std::time::{Instant, Duration};
use std::i32;
......@@ -609,16 +608,14 @@ fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
}
fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
llmod_id: &str,
llvm_module: &ModuleLlvm,
link_meta: &LinkMeta)
-> (ContextRef, ModuleRef, EncodedMetadata) {
-> EncodedMetadata {
use std::io::Write;
use flate2::Compression;
use flate2::write::DeflateEncoder;
let (metadata_llcx, metadata_llmod) = unsafe {
context::create_context_and_module(tcx.sess, llmod_id)
};
let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod());
#[derive(PartialEq, Eq, PartialOrd, Ord)]
enum MetadataKind {
......@@ -641,14 +638,12 @@ enum MetadataKind {
}).max().unwrap_or(MetadataKind::None);
if kind == MetadataKind::None {
return (metadata_llcx,
metadata_llmod,
EncodedMetadata::new());
return EncodedMetadata::new();
}
let metadata = tcx.encode_metadata(link_meta);
if kind == MetadataKind::Uncompressed {
return (metadata_llcx, metadata_llmod, metadata);
return metadata;
}
assert!(kind == MetadataKind::Compressed);
......@@ -676,7 +671,7 @@ enum MetadataKind {
let directive = CString::new(directive).unwrap();
llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
}
return (metadata_llcx, metadata_llmod, metadata);
return metadata;
}
pub struct ValueIter {
......@@ -698,7 +693,7 @@ fn next(&mut self) -> Option<ValueRef> {
}
}
pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
pub fn iter_globals(llmod: &llvm::Module) -> ValueIter {
unsafe {
ValueIter {
cur: llvm::LLVMGetFirstGlobal(llmod),
......@@ -731,19 +726,15 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Codegen the metadata.
let llmod_id = "metadata";
let (metadata_llcx, metadata_llmod, metadata) =
time(tcx.sess, "write metadata", || {
write_metadata(tcx, llmod_id, &link_meta)
});
let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id);
let metadata = time(tcx.sess, "write metadata", || {
write_metadata(tcx, &metadata_llvm_module, &link_meta)
});
let metadata_module = ModuleCodegen {
name: link::METADATA_MODULE_NAME.to_string(),
llmod_id: llmod_id.to_string(),
source: ModuleSource::Codegened(ModuleLlvm {
llcx: metadata_llcx,
llmod: metadata_llmod,
tm: create_target_machine(tcx.sess, false),
}),
source: ModuleSource::Codegened(metadata_llvm_module),
kind: ModuleKind::Metadata,
};
......@@ -803,13 +794,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
unsafe {
let llmod_id = "allocator";
let (llcx, llmod) =
context::create_context_and_module(tcx.sess, llmod_id);
let modules = ModuleLlvm {
llmod,
llcx,
tm: create_target_machine(tcx.sess, false),
};
let modules = ModuleLlvm::new(tcx.sess, llmod_id);
time(tcx.sess, "write allocator module", || {
allocator::codegen(tcx, &modules, kind)
});
......@@ -1200,8 +1185,9 @@ fn module_codegen<'a, 'tcx>(
.to_fingerprint().to_hex());
// Instantiate monomorphizations without filling out definitions yet...
let cx = CodegenCx::new(tcx, cgu, &llmod_id);
let module = {
let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
let stats = {
let cx = CodegenCx::new(tcx, cgu, &llvm_module);
let mono_items = cx.codegen_unit
.items_in_deterministic_order(cx.tcx);
for &(mono_item, (linkage, visibility)) in &mono_items {
......@@ -1248,21 +1234,15 @@ fn module_codegen<'a, 'tcx>(
debuginfo::finalize(&cx);
}
let llvm_module = ModuleLlvm {
llcx: cx.llcx,
llmod: cx.llmod,
tm: create_target_machine(cx.sess(), false),
};
ModuleCodegen {
name: cgu_name,
source: ModuleSource::Codegened(llvm_module),
kind: ModuleKind::Regular,
llmod_id,
}
cx.stats.into_inner()
};
(cx.into_stats(), module)
(stats, ModuleCodegen {
name: cgu_name,
source: ModuleSource::Codegened(llvm_module),
kind: ModuleKind::Regular,
llmod_id,
})
}
}
......
......@@ -13,7 +13,7 @@
//! Code that is useful in various codegen modules.
use llvm;
use llvm::{ValueRef, ContextRef, TypeKind};
use llvm::{ValueRef, TypeKind};
use llvm::{True, False, Bool, OperandBundleDef};
use rustc::hir::def_id::DefId;
use rustc::middle::lang_items::LangItem;
......@@ -225,7 +225,7 @@ pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef {
C_struct_in_context(cx.llcx, elts, packed)
}
pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
pub fn C_struct_in_context(llcx: &llvm::Context, elts: &[ValueRef], packed: bool) -> ValueRef {
unsafe {
llvm::LLVMConstStructInContext(llcx,
elts.as_ptr(), elts.len() as c_uint,
......@@ -249,7 +249,7 @@ pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef {
C_bytes_in_context(cx.llcx, bytes)
}
pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
pub fn C_bytes_in_context(llcx: &llvm::Context, bytes: &[u8]) -> ValueRef {
unsafe {
let ptr = bytes.as_ptr() as *const c_char;
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
......
......@@ -10,7 +10,7 @@
use common;
use llvm;
use llvm::{ContextRef, ModuleRef, ValueRef};
use llvm::ValueRef;
use rustc::dep_graph::DepGraphSafe;
use rustc::hir;
use rustc::hir::def_id::DefId;
......@@ -42,16 +42,16 @@
use abi::Abi;
/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
/// `ContextRef` so that several compilation units may be optimized in parallel.
/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`.
/// `llvm::Context` so that several compilation units may be optimized in parallel.
/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
pub struct CodegenCx<'a, 'tcx: 'a> {
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub check_overflow: bool,
pub use_dll_storage_attrs: bool,
pub tls_model: llvm::ThreadLocalMode,
pub llmod: ModuleRef,
pub llcx: ContextRef,
pub llmod: &'a llvm::Module,
pub llcx: &'a llvm::Context,
pub stats: RefCell<Stats>,
pub codegen_unit: Arc<CodegenUnit<'tcx>>,
......@@ -94,7 +94,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
pub isize_ty: Type,
pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
pub dbg_cx: Option<debuginfo::CrateDebugContext<'a, 'tcx>>,
eh_personality: Cell<Option<ValueRef>>,
eh_unwind_resume: Cell<Option<ValueRef>>,
......@@ -155,8 +155,7 @@ pub fn is_pie_binary(sess: &Session) -> bool {
!is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
}
pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
pub unsafe fn create_module(sess: &Session, llcx: &'ll llvm::Context, mod_name: &str) -> &'ll llvm::Module {
let mod_name = CString::new(mod_name).unwrap();
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
......@@ -208,13 +207,13 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont
llvm::LLVMRustSetModulePIELevel(llmod);
}
(llcx, llmod)
llmod
}
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
codegen_unit: Arc<CodegenUnit<'tcx>>,
llmod_id: &str)
llvm_module: &'a ::ModuleLlvm)
-> CodegenCx<'a, 'tcx> {
// An interesting part of Windows which MSVC forces our hand on (and
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
......@@ -265,55 +264,48 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let tls_model = get_tls_model(&tcx.sess);
unsafe {
let (llcx, llmod) = create_context_and_module(&tcx.sess,
&llmod_id[..]);
let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
let dctx = debuginfo::CrateDebugContext::new(llmod);
debuginfo::metadata::compile_unit_metadata(tcx,
&codegen_unit.name().as_str(),
&dctx);
Some(dctx)
} else {
None
};
let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
CodegenCx {
tcx,
check_overflow,
use_dll_storage_attrs,
tls_model,
llmod,
llcx,
stats: RefCell::new(Stats::default()),
codegen_unit,
instances: RefCell::new(FxHashMap()),
vtables: RefCell::new(FxHashMap()),
const_cstr_cache: RefCell::new(FxHashMap()),
const_unsized: RefCell::new(FxHashMap()),
const_globals: RefCell::new(FxHashMap()),
statics: RefCell::new(FxHashMap()),
statics_to_rauw: RefCell::new(Vec::new()),
used_statics: RefCell::new(Vec::new()),
lltypes: RefCell::new(FxHashMap()),
scalar_lltypes: RefCell::new(FxHashMap()),
pointee_infos: RefCell::new(FxHashMap()),
isize_ty,
dbg_cx,
eh_personality: Cell::new(None),
eh_unwind_resume: Cell::new(None),
rust_try_fn: Cell::new(None),
intrinsics: RefCell::new(FxHashMap()),
local_gen_sym_counter: Cell::new(0),
}
}
}
let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
pub fn into_stats(self) -> Stats {
self.stats.into_inner()
let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
let dctx = debuginfo::CrateDebugContext::new(llmod);
debuginfo::metadata::compile_unit_metadata(tcx,
&codegen_unit.name().as_str(),
&dctx);
Some(dctx)
} else {
None
};
let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
CodegenCx {
tcx,
check_overflow,
use_dll_storage_attrs,
tls_model,
llmod,
llcx,
stats: RefCell::new(Stats::default()),
codegen_unit,
instances: RefCell::new(FxHashMap()),
vtables: RefCell::new(FxHashMap()),
const_cstr_cache: RefCell::new(FxHashMap()),
const_unsized: RefCell::new(FxHashMap()),
const_globals: RefCell::new(FxHashMap()),
statics: RefCell::new(FxHashMap()),
statics_to_rauw: RefCell::new(Vec::new()),
used_statics: RefCell::new(Vec::new()),
lltypes: RefCell::new(FxHashMap()),
scalar_lltypes: RefCell::new(FxHashMap()),
pointee_infos: RefCell::new(FxHashMap()),
isize_ty,
dbg_cx,
eh_personality: Cell::new(None),
eh_unwind_resume: Cell::new(None),
rust_try_fn: Cell::new(None),
intrinsics: RefCell::new(FxHashMap()),
local_gen_sym_counter: Cell::new(0),
}
}
}
......
......@@ -862,7 +862,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt,
return unit_metadata;
};
fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef {
fn path_to_mdstring(llcx: &llvm::Context, path: &Path) -> llvm::ValueRef {
let path_str = path2cstr(path);
unsafe {
llvm::LLVMMDStringInContext(llcx,
......
......@@ -21,7 +21,7 @@
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
use llvm;
use llvm::{ModuleRef, ContextRef, ValueRef};
use llvm::ValueRef;
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, CrateNum};
......@@ -67,9 +67,9 @@
const DW_TAG_arg_variable: c_uint = 0x101;
/// A context object for maintaining all state needed by the debuginfo module.
pub struct CrateDebugContext<'tcx> {
llcontext: ContextRef,
llmod: ModuleRef,
pub struct CrateDebugContext<'a, 'tcx> {
llcontext: &'a llvm::Context,
llmod: &'a llvm::Module,
builder: DIBuilderRef,
created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>,
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), DIType>>,
......@@ -82,8 +82,8 @@ pub struct CrateDebugContext<'tcx> {
composite_types_completed: RefCell<FxHashSet<DIType>>,
}
impl<'tcx> CrateDebugContext<'tcx> {
pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
pub fn new(llmod: &'a llvm::Module) -> Self {
debug!("CrateDebugContext::new");
let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
// DIBuilder inherits context from the module, so we'd better use the same one
......
......@@ -50,7 +50,7 @@ pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc {
#[inline]
pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>)
-> &'a CrateDebugContext<'tcx> {
-> &'a CrateDebugContext<'a, 'tcx> {
cx.dbg_cx.as_ref().unwrap()
}
......
......@@ -20,9 +20,11 @@
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
#![feature(custom_attribute)]
#![feature(extern_types)]
#![feature(fs_read_write)]
#![feature(in_band_lifetimes)]
#![allow(unused_attributes)]
#![feature(libc)]
#![feature(quote)]
......@@ -34,6 +36,7 @@
#![feature(link_args)]
#![feature(static_nobundle)]
use back::write::create_target_machine;
use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol;
......@@ -340,22 +343,41 @@ enum ModuleSource {
Codegened(ModuleLlvm),
}
#[derive(Debug)]
struct ModuleLlvm {
llcx: llvm::ContextRef,
llmod: llvm::ModuleRef,
tm: llvm::TargetMachineRef,
llcx: &'static mut llvm::Context,
llmod_raw: *const llvm::Module,
tm: &'static mut llvm::TargetMachine,
}
unsafe impl Send for ModuleLlvm { }
unsafe impl Sync for ModuleLlvm { }
impl ModuleLlvm {
fn new(sess: &Session, mod_name: &str) -> Self {
unsafe {
let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _;
ModuleLlvm {
llmod_raw,
llcx,
tm: create_target_machine(sess, false),
}
}
}
fn llmod(&self) -> &llvm::Module {
unsafe {
&*self.llmod_raw
}
}
}
impl Drop for ModuleLlvm {
fn drop(&mut self) {
unsafe {
llvm::LLVMDisposeModule(self.llmod);
llvm::LLVMContextDispose(self.llcx);
llvm::LLVMRustDisposeTargetMachine(self.tm);
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
}
}
}
......
......@@ -127,7 +127,7 @@ pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
// function.
// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
pub fn SetUniqueComdat(llmod: &Module, val: ValueRef) {
unsafe {
LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
}
......
......@@ -11,7 +11,7 @@
#![allow(non_upper_case_globals)]
use llvm;
use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind};
use llvm::{TypeRef, Bool, False, True, TypeKind};
use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
use context::CodegenCx;
......@@ -77,7 +77,7 @@ pub fn i8(cx: &CodegenCx) -> Type {
ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
}
pub fn i8_llcx(llcx: ContextRef) -> Type {
pub fn i8_llcx(llcx: &llvm::Context) -> Type {
ty!(llvm::LLVMInt8TypeInContext(llcx))
}
......@@ -103,7 +103,7 @@ pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type {
}
// Creates an integer type with the given number of bits, e.g. i24
pub fn ix_llcx(llcx: ContextRef, num_bits: u64) -> Type {
pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> Type {
ty!(llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint))
}
......@@ -127,7 +127,7 @@ pub fn i8p(cx: &CodegenCx) -> Type {
Type::i8(cx).ptr_to()
}
pub fn i8p_llcx(llcx: ContextRef) -> Type {
pub fn i8p_llcx(llcx: &llvm::Context) -> Type {
Type::i8_llcx(llcx).ptr_to()
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册