CommonWriteMethods are not static any more
This commit is contained in:
parent
3aee77277e
commit
4cc18d3de5
10 changed files with 179 additions and 85 deletions
|
@ -26,6 +26,7 @@ use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_codegen_utils::symbol_export;
|
use rustc_codegen_utils::symbol_export;
|
||||||
use time_graph::Timeline;
|
use time_graph::Timeline;
|
||||||
use {ModuleCodegen, ModuleLlvm, ModuleKind};
|
use {ModuleCodegen, ModuleLlvm, ModuleKind};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
|
|
||||||
|
@ -767,6 +768,7 @@ impl ThinModule {
|
||||||
llmod_raw,
|
llmod_raw,
|
||||||
llcx,
|
llcx,
|
||||||
tm,
|
tm,
|
||||||
|
phantom: PhantomData
|
||||||
},
|
},
|
||||||
name: self.name().to_string(),
|
name: self.name().to_string(),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
|
|
|
@ -24,7 +24,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitize
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::util::nodemap::FxHashMap;
|
use rustc::util::nodemap::FxHashMap;
|
||||||
use time_graph::{self, TimeGraph, Timeline};
|
use time_graph::{self, TimeGraph, Timeline};
|
||||||
use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
|
use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic, BasicBlock, True};
|
||||||
use llvm_util;
|
use llvm_util;
|
||||||
use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm,
|
use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm,
|
||||||
CachedModuleCodegen};
|
CachedModuleCodegen};
|
||||||
|
@ -45,10 +45,12 @@ use syntax::ext::hygiene::Mark;
|
||||||
use syntax_pos::MultiSpan;
|
use syntax_pos::MultiSpan;
|
||||||
use syntax_pos::symbol::Symbol;
|
use syntax_pos::symbol::Symbol;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use context::{is_pie_binary, get_reloc_model, CodegenCx};
|
use context::{is_pie_binary, get_reloc_model};
|
||||||
use interfaces::CommonWriteMethods;
|
use interfaces::{Backend, CommonWriteMethods};
|
||||||
use jobserver::{Client, Acquired};
|
use jobserver::{Client, Acquired};
|
||||||
use rustc_demangle;
|
use rustc_demangle;
|
||||||
|
use value::Value;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::ffi::{CString, CStr};
|
use std::ffi::{CString, CStr};
|
||||||
|
@ -351,7 +353,7 @@ struct AssemblerCommand {
|
||||||
|
|
||||||
/// Additional resources used by optimize_and_codegen (not module specific)
|
/// Additional resources used by optimize_and_codegen (not module specific)
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CodegenContext {
|
pub struct CodegenContext<'ll> {
|
||||||
// Resources needed when running LTO
|
// Resources needed when running LTO
|
||||||
pub time_passes: bool,
|
pub time_passes: bool,
|
||||||
pub lto: Lto,
|
pub lto: Lto,
|
||||||
|
@ -393,9 +395,12 @@ pub struct CodegenContext {
|
||||||
time_graph: Option<TimeGraph>,
|
time_graph: Option<TimeGraph>,
|
||||||
// The assembler command if no_integrated_as option is enabled, None otherwise
|
// The assembler command if no_integrated_as option is enabled, None otherwise
|
||||||
assembler_cmd: Option<Arc<AssemblerCommand>>,
|
assembler_cmd: Option<Arc<AssemblerCommand>>,
|
||||||
|
// This field is used to give a lifetime parameter to the struct so that it can implement
|
||||||
|
// the Backend trait.
|
||||||
|
phantom: PhantomData<&'ll ()>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodegenContext {
|
impl CodegenContext<'ll> {
|
||||||
pub fn create_diag_handler(&self) -> Handler {
|
pub fn create_diag_handler(&self) -> Handler {
|
||||||
Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
|
Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
|
||||||
}
|
}
|
||||||
|
@ -423,13 +428,49 @@ impl CodegenContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ll> Backend for CodegenContext<'ll> {
|
||||||
|
type Value = &'ll Value;
|
||||||
|
type BasicBlock = &'ll BasicBlock;
|
||||||
|
type Type = &'ll Type;
|
||||||
|
type Context = &'ll llvm::Context;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommonWriteMethods for CodegenContext<'ll> {
|
||||||
|
fn val_ty(&self, v: &'ll Value) -> &'ll Type {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMTypeOf(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
let ptr = bytes.as_ptr() as *const c_char;
|
||||||
|
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_struct_in_context(
|
||||||
|
&self,
|
||||||
|
llcx: &'a llvm::Context,
|
||||||
|
elts: &[&'a Value],
|
||||||
|
packed: bool,
|
||||||
|
) -> &'a Value {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMConstStructInContext(llcx,
|
||||||
|
elts.as_ptr(), elts.len() as c_uint,
|
||||||
|
packed as llvm::Bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct DiagnosticHandlers<'a> {
|
pub struct DiagnosticHandlers<'a> {
|
||||||
data: *mut (&'a CodegenContext, &'a Handler),
|
data: *mut (&'a CodegenContext<'a>, &'a Handler),
|
||||||
llcx: &'a llvm::Context,
|
llcx: &'a llvm::Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DiagnosticHandlers<'a> {
|
impl<'a> DiagnosticHandlers<'a> {
|
||||||
pub fn new(cgcx: &'a CodegenContext,
|
pub fn new(cgcx: &'a CodegenContext<'a>,
|
||||||
handler: &'a Handler,
|
handler: &'a Handler,
|
||||||
llcx: &'a llvm::Context) -> Self {
|
llcx: &'a llvm::Context) -> Self {
|
||||||
let data = Box::into_raw(Box::new((cgcx, handler)));
|
let data = Box::into_raw(Box::new((cgcx, handler)));
|
||||||
|
@ -884,10 +925,10 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
|
||||||
llcx: &llvm::Context,
|
llcx: &llvm::Context,
|
||||||
llmod: &llvm::Module,
|
llmod: &llvm::Module,
|
||||||
bitcode: Option<&[u8]>) {
|
bitcode: Option<&[u8]>) {
|
||||||
let llconst = CodegenCx::c_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
|
let llconst = cgcx.c_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
|
||||||
let llglobal = llvm::LLVMAddGlobal(
|
let llglobal = llvm::LLVMAddGlobal(
|
||||||
llmod,
|
llmod,
|
||||||
CodegenCx::val_ty(llconst),
|
cgcx.val_ty(llconst),
|
||||||
"rustc.embedded.module\0".as_ptr() as *const _,
|
"rustc.embedded.module\0".as_ptr() as *const _,
|
||||||
);
|
);
|
||||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||||
|
@ -904,10 +945,10 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
|
||||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||||
|
|
||||||
let llconst = CodegenCx::c_bytes_in_context(llcx, &[]);
|
let llconst = cgcx.c_bytes_in_context(llcx, &[]);
|
||||||
let llglobal = llvm::LLVMAddGlobal(
|
let llglobal = llvm::LLVMAddGlobal(
|
||||||
llmod,
|
llmod,
|
||||||
CodegenCx::val_ty(llconst),
|
cgcx.val_ty(llconst),
|
||||||
"rustc.embedded.cmdline\0".as_ptr() as *const _,
|
"rustc.embedded.cmdline\0".as_ptr() as *const _,
|
||||||
);
|
);
|
||||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||||
|
@ -1614,6 +1655,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
|
target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
|
||||||
debuginfo: tcx.sess.opts.debuginfo,
|
debuginfo: tcx.sess.opts.debuginfo,
|
||||||
assembler_cmd,
|
assembler_cmd,
|
||||||
|
phantom: PhantomData
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is the "main loop" of parallel work happening for parallel codegen.
|
// This is the "main loop" of parallel work happening for parallel codegen.
|
||||||
|
@ -2108,7 +2150,7 @@ pub const CODEGEN_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
||||||
const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
||||||
time_graph::WorkPackageKind(&["#7DB67A", "#C6EEC4", "#ACDAAA", "#579354", "#3E6F3C"]);
|
time_graph::WorkPackageKind(&["#7DB67A", "#C6EEC4", "#ACDAAA", "#579354", "#3E6F3C"]);
|
||||||
|
|
||||||
fn spawn_work(cgcx: CodegenContext, work: WorkItem) {
|
fn spawn_work(cgcx: CodegenContext<'static>, work: WorkItem) {
|
||||||
let depth = time_depth();
|
let depth = time_depth();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
|
|
@ -334,12 +334,13 @@ pub fn coerce_unsized_into(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cast_shift_expr_rhs(
|
pub fn cast_shift_expr_rhs(
|
||||||
cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
|
bx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b))
|
cast_shift_rhs(bx, op, lhs, rhs, |a, b| bx.trunc(a, b), |a, b| bx.zext(a, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
|
fn cast_shift_rhs<'ll, F, G>(bx: &Builder<'_, 'll, '_>,
|
||||||
|
op: hir::BinOpKind,
|
||||||
lhs: &'ll Value,
|
lhs: &'ll Value,
|
||||||
rhs: &'ll Value,
|
rhs: &'ll Value,
|
||||||
trunc: F,
|
trunc: F,
|
||||||
|
@ -350,8 +351,8 @@ fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
|
||||||
{
|
{
|
||||||
// Shifts may have any size int on the rhs
|
// Shifts may have any size int on the rhs
|
||||||
if op.is_shift() {
|
if op.is_shift() {
|
||||||
let mut rhs_llty = CodegenCx::val_ty(rhs);
|
let mut rhs_llty = bx.cx().val_ty(rhs);
|
||||||
let mut lhs_llty = CodegenCx::val_ty(lhs);
|
let mut lhs_llty = bx.cx().val_ty(lhs);
|
||||||
if rhs_llty.kind() == TypeKind::Vector {
|
if rhs_llty.kind() == TypeKind::Vector {
|
||||||
rhs_llty = rhs_llty.element_type()
|
rhs_llty = rhs_llty.element_type()
|
||||||
}
|
}
|
||||||
|
@ -392,7 +393,7 @@ pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll>(
|
||||||
bx: &Builder<'_ ,'ll, '_, &'ll Value>,
|
bx: &Builder<'_ ,'ll, '_, &'ll Value>,
|
||||||
val: &'ll Value
|
val: &'ll Value
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
if CodegenCx::val_ty(val) == Type::i1(bx.cx()) {
|
if bx.cx().val_ty(val) == Type::i1(bx.cx()) {
|
||||||
bx.zext(val, Type::i8(bx.cx()))
|
bx.zext(val, Type::i8(bx.cx()))
|
||||||
} else {
|
} else {
|
||||||
val
|
val
|
||||||
|
@ -433,7 +434,7 @@ pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll>(
|
||||||
if flags.contains(MemFlags::NONTEMPORAL) {
|
if flags.contains(MemFlags::NONTEMPORAL) {
|
||||||
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
||||||
let val = bx.load(src, src_align);
|
let val = bx.load(src, src_align);
|
||||||
let ptr = bx.pointercast(dst, CodegenCx::val_ty(val).ptr_to());
|
let ptr = bx.pointercast(dst, bx.cx().val_ty(val).ptr_to());
|
||||||
bx.store_with_flags(val, ptr, dst_align, flags);
|
bx.store_with_flags(val, ptr, dst_align, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -648,12 +649,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||||
DeflateEncoder::new(&mut compressed, Compression::fast())
|
DeflateEncoder::new(&mut compressed, Compression::fast())
|
||||||
.write_all(&metadata.raw_data).unwrap();
|
.write_all(&metadata.raw_data).unwrap();
|
||||||
|
|
||||||
let llmeta = CodegenCx::c_bytes_in_context(metadata_llcx, &compressed);
|
let llmeta = llvm_module.c_bytes_in_context(metadata_llcx, &compressed);
|
||||||
let llconst = CodegenCx::c_struct_in_context(metadata_llcx, &[llmeta], false);
|
let llconst = llvm_module.c_struct_in_context(metadata_llcx, &[llmeta], false);
|
||||||
let name = exported_symbols::metadata_symbol_name(tcx);
|
let name = exported_symbols::metadata_symbol_name(tcx);
|
||||||
let buf = CString::new(name).unwrap();
|
let buf = CString::new(name).unwrap();
|
||||||
let llglobal = unsafe {
|
let llglobal = unsafe {
|
||||||
llvm::LLVMAddGlobal(metadata_llmod, CodegenCx::val_ty(llconst), buf.as_ptr())
|
llvm::LLVMAddGlobal(metadata_llmod, llvm_module.val_ty(llconst), buf.as_ptr())
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||||
|
@ -1139,7 +1140,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, '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() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let bitcast = llvm::LLVMConstPointerCast(new_g, CodegenCx::val_ty(old_g));
|
let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
|
||||||
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
||||||
llvm::LLVMDeleteGlobal(old_g);
|
llvm::LLVMDeleteGlobal(old_g);
|
||||||
}
|
}
|
||||||
|
@ -1154,7 +1155,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let g = llvm::LLVMAddGlobal(cx.llmod,
|
let g = llvm::LLVMAddGlobal(cx.llmod,
|
||||||
CodegenCx::val_ty(array),
|
cx.val_ty(array),
|
||||||
name.as_ptr());
|
name.as_ptr());
|
||||||
llvm::LLVMSetInitializer(g, array);
|
llvm::LLVMSetInitializer(g, array);
|
||||||
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
|
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
|
||||||
|
|
|
@ -527,7 +527,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let llty = CodegenCx::val_ty(load);
|
let llty = self.cx.val_ty(load);
|
||||||
let v = [
|
let v = [
|
||||||
self.cx.c_uint_big(llty, range.start),
|
self.cx.c_uint_big(llty, range.start),
|
||||||
self.cx.c_uint_big(llty, range.end)
|
self.cx.c_uint_big(llty, range.end)
|
||||||
|
@ -760,7 +760,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
|
|
||||||
let argtys = inputs.iter().map(|v| {
|
let argtys = inputs.iter().map(|v| {
|
||||||
debug!("Asm Input Type: {:?}", *v);
|
debug!("Asm Input Type: {:?}", *v);
|
||||||
CodegenCx::val_ty(*v)
|
self.cx.val_ty(*v)
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
debug!("Asm Output Type: {:?}", output);
|
debug!("Asm Output Type: {:?}", output);
|
||||||
|
@ -859,7 +859,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
|
|
||||||
fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
|
fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
|
||||||
unsafe {
|
unsafe {
|
||||||
let elt_ty = CodegenCx::val_ty(elt);
|
let elt_ty = self.cx.val_ty(elt);
|
||||||
let undef = llvm::LLVMGetUndef(type_::Type::vector(elt_ty, num_elts as u64));
|
let undef = llvm::LLVMGetUndef(type_::Type::vector(elt_ty, num_elts as u64));
|
||||||
let vec = self.insert_element(undef, elt, CodegenCx::c_i32(self.cx, 0));
|
let vec = self.insert_element(undef, elt, CodegenCx::c_i32(self.cx, 0));
|
||||||
let vec_i32_ty = type_::Type::vector(type_::Type::i32(self.cx), num_elts as u64);
|
let vec_i32_ty = type_::Type::vector(type_::Type::i32(self.cx), num_elts as u64);
|
||||||
|
@ -1139,8 +1139,8 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
fn check_store<'b>(&self,
|
fn check_store<'b>(&self,
|
||||||
val: &'ll Value,
|
val: &'ll Value,
|
||||||
ptr: &'ll Value) -> &'ll Value {
|
ptr: &'ll Value) -> &'ll Value {
|
||||||
let dest_ptr_ty = CodegenCx::val_ty(ptr);
|
let dest_ptr_ty = self.cx.val_ty(ptr);
|
||||||
let stored_ty = CodegenCx::val_ty(val);
|
let stored_ty = self.cx.val_ty(val);
|
||||||
let stored_ptr_ty = stored_ty.ptr_to();
|
let stored_ptr_ty = stored_ty.ptr_to();
|
||||||
|
|
||||||
assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
|
assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
|
||||||
|
@ -1160,7 +1160,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
typ: &str,
|
typ: &str,
|
||||||
llfn: &'ll Value,
|
llfn: &'ll Value,
|
||||||
args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
|
args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
|
||||||
let mut fn_ty = CodegenCx::val_ty(llfn);
|
let mut fn_ty = self.cx.val_ty(llfn);
|
||||||
// Strip off pointers
|
// Strip off pointers
|
||||||
while fn_ty.kind() == llvm::TypeKind::Pointer {
|
while fn_ty.kind() == llvm::TypeKind::Pointer {
|
||||||
fn_ty = fn_ty.element_type();
|
fn_ty = fn_ty.element_type();
|
||||||
|
@ -1172,7 +1172,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
let param_tys = fn_ty.func_params();
|
let param_tys = fn_ty.func_params();
|
||||||
|
|
||||||
let all_args_match = param_tys.iter()
|
let all_args_match = param_tys.iter()
|
||||||
.zip(args.iter().map(|&v| CodegenCx::val_ty(v)))
|
.zip(args.iter().map(|&v| self.cx().val_ty(v)))
|
||||||
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
||||||
|
|
||||||
if all_args_match {
|
if all_args_match {
|
||||||
|
@ -1183,7 +1183,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
.zip(args.iter())
|
.zip(args.iter())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (expected_ty, &actual_val))| {
|
.map(|(i, (expected_ty, &actual_val))| {
|
||||||
let actual_ty = CodegenCx::val_ty(actual_val);
|
let actual_ty = self.cx().val_ty(actual_val);
|
||||||
if expected_ty != actual_ty {
|
if expected_ty != actual_ty {
|
||||||
debug!("Type mismatch in function call of {:?}. \
|
debug!("Type mismatch in function call of {:?}. \
|
||||||
Expected {:?} for param {}, got {:?}; injecting bitcast",
|
Expected {:?} for param {}, got {:?}; injecting bitcast",
|
||||||
|
|
|
@ -84,7 +84,7 @@ pub fn get_fn(
|
||||||
// This can occur on either a crate-local or crate-external
|
// This can occur on either a crate-local or crate-external
|
||||||
// reference. It also occurs when testing libcore and in some
|
// reference. It also occurs when testing libcore and in some
|
||||||
// other weird situations. Annoying.
|
// other weird situations. Annoying.
|
||||||
if CodegenCx::val_ty(llfn) != llptrty {
|
if cx.val_ty(llfn) != llptrty {
|
||||||
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
|
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
|
||||||
consts::ptrcast(llfn, llptrty)
|
consts::ptrcast(llfn, llptrty)
|
||||||
} else {
|
} else {
|
||||||
|
@ -93,7 +93,7 @@ pub fn get_fn(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let llfn = declare::declare_fn(cx, &sym, sig);
|
let llfn = declare::declare_fn(cx, &sym, sig);
|
||||||
assert_eq!(CodegenCx::val_ty(llfn), llptrty);
|
assert_eq!(cx.val_ty(llfn), llptrty);
|
||||||
debug!("get_fn: not casting pointer!");
|
debug!("get_fn: not casting pointer!");
|
||||||
|
|
||||||
if instance.def.is_inline(tcx) {
|
if instance.def.is_inline(tcx) {
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
|
||||||
s.len() as c_uint,
|
s.len() as c_uint,
|
||||||
!null_terminated as Bool);
|
!null_terminated as Bool);
|
||||||
let sym = &self.generate_local_symbol_name("str");
|
let sym = &self.generate_local_symbol_name("str");
|
||||||
let g = declare::define_global(&self, &sym[..], Self::val_ty(sc)).unwrap_or_else(||{
|
let g = declare::define_global(&self, &sym[..], &self.val_ty(sc)).unwrap_or_else(||{
|
||||||
bug!("symbol `{}` is already defined", sym);
|
bug!("symbol `{}` is already defined", sym);
|
||||||
});
|
});
|
||||||
llvm::LLVMSetInitializer(g, sc);
|
llvm::LLVMSetInitializer(g, sc);
|
||||||
|
@ -318,19 +318,7 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
|
||||||
elts: &[&'ll Value],
|
elts: &[&'ll Value],
|
||||||
packed: bool
|
packed: bool
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
Self::c_struct_in_context(&self.llcx, elts, packed)
|
&self.c_struct_in_context(&self.llcx, elts, packed)
|
||||||
}
|
|
||||||
|
|
||||||
fn c_struct_in_context(
|
|
||||||
llcx: &'a llvm::Context,
|
|
||||||
elts: &[&'a Value],
|
|
||||||
packed: bool,
|
|
||||||
) -> &'a Value {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMConstStructInContext(llcx,
|
|
||||||
elts.as_ptr(), elts.len() as c_uint,
|
|
||||||
packed as Bool)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
|
fn c_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
|
||||||
|
@ -346,7 +334,7 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c_bytes(&self, bytes: &[u8]) -> &'ll Value {
|
fn c_bytes(&self, bytes: &[u8]) -> &'ll Value {
|
||||||
Self::c_bytes_in_context(&self.llcx, bytes)
|
&self.c_bytes_in_context(&self.llcx, bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
|
fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
|
||||||
|
@ -411,6 +399,35 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ll, 'tcx : 'll> CommonWriteMethods for CodegenCx<'ll, 'tcx> {
|
||||||
|
fn val_ty(&self, v: &'ll Value) -> &'ll Type {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMTypeOf(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
let ptr = bytes.as_ptr() as *const c_char;
|
||||||
|
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_struct_in_context(
|
||||||
|
&self,
|
||||||
|
llcx: &'a llvm::Context,
|
||||||
|
elts: &[&'a Value],
|
||||||
|
packed: bool,
|
||||||
|
) -> &'a Value {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMConstStructInContext(llcx,
|
||||||
|
elts.as_ptr(), elts.len() as c_uint,
|
||||||
|
packed as Bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
|
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
|
||||||
((hi as u128) << 64) | (lo as u128)
|
((hi as u128) << 64) | (lo as u128)
|
||||||
|
@ -461,7 +478,7 @@ pub fn build_unchecked_rshift(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
|
fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
|
||||||
let rhs_llty = CodegenCx::val_ty(rhs);
|
let rhs_llty = bx.cx().val_ty(rhs);
|
||||||
bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
|
bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,18 +506,3 @@ pub fn shift_mask_val(
|
||||||
_ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
|
_ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ll, 'tcx : 'll> CommonWriteMethods for CodegenCx<'ll, 'tcx> {
|
|
||||||
fn val_ty(v: &'ll Value) -> &'ll Type {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMTypeOf(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn c_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
|
|
||||||
unsafe {
|
|
||||||
let ptr = bytes.as_ptr() as *const c_char;
|
|
||||||
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -74,13 +74,13 @@ pub fn addr_of_mut(
|
||||||
Some(kind) if !cx.tcx.sess.fewer_names() => {
|
Some(kind) if !cx.tcx.sess.fewer_names() => {
|
||||||
let name = cx.generate_local_symbol_name(kind);
|
let name = cx.generate_local_symbol_name(kind);
|
||||||
let gv = declare::define_global(cx, &name[..],
|
let gv = declare::define_global(cx, &name[..],
|
||||||
CodegenCx::val_ty(cv)).unwrap_or_else(||{
|
cx.val_ty(cv)).unwrap_or_else(||{
|
||||||
bug!("symbol `{}` is already defined", name);
|
bug!("symbol `{}` is already defined", name);
|
||||||
});
|
});
|
||||||
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
|
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
|
||||||
gv
|
gv
|
||||||
},
|
},
|
||||||
_ => declare::define_private_global(cx, CodegenCx::val_ty(cv)),
|
_ => declare::define_private_global(cx, cx.val_ty(cv)),
|
||||||
};
|
};
|
||||||
llvm::LLVMSetInitializer(gv, cv);
|
llvm::LLVMSetInitializer(gv, cv);
|
||||||
set_global_alignment(cx, gv, align);
|
set_global_alignment(cx, gv, align);
|
||||||
|
@ -312,7 +312,7 @@ pub fn codegen_static<'a, 'tcx>(
|
||||||
|
|
||||||
// boolean SSA values are i1, but they have to be stored in i8 slots,
|
// boolean SSA values are i1, but they have to be stored in i8 slots,
|
||||||
// otherwise some LLVM optimization passes don't work as expected
|
// otherwise some LLVM optimization passes don't work as expected
|
||||||
let mut val_llty = CodegenCx::val_ty(v);
|
let mut val_llty = cx.val_ty(v);
|
||||||
let v = if val_llty == Type::i1(cx) {
|
let v = if val_llty == Type::i1(cx) {
|
||||||
val_llty = Type::i8(cx);
|
val_llty = Type::i8(cx);
|
||||||
llvm::LLVMConstZExt(v, val_llty)
|
llvm::LLVMConstZExt(v, val_llty)
|
||||||
|
|
|
@ -40,11 +40,6 @@ pub trait CommonMethods : Backend + CommonWriteMethods {
|
||||||
elts: &[Self::Value],
|
elts: &[Self::Value],
|
||||||
packed: bool
|
packed: bool
|
||||||
) -> Self::Value;
|
) -> Self::Value;
|
||||||
fn c_struct_in_context(
|
|
||||||
llcx: Self::Context,
|
|
||||||
elts: &[Self::Value],
|
|
||||||
packed: bool,
|
|
||||||
) -> Self::Value;
|
|
||||||
fn c_array(ty: Self::Type, elts: &[Self::Value]) -> Self::Value;
|
fn c_array(ty: Self::Type, elts: &[Self::Value]) -> Self::Value;
|
||||||
fn c_vector(elts: &[Self::Value]) -> Self::Value;
|
fn c_vector(elts: &[Self::Value]) -> Self::Value;
|
||||||
fn c_bytes(&self, bytes: &[u8]) -> Self::Value;
|
fn c_bytes(&self, bytes: &[u8]) -> Self::Value;
|
||||||
|
@ -58,6 +53,12 @@ pub trait CommonMethods : Backend + CommonWriteMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CommonWriteMethods : Backend {
|
pub trait CommonWriteMethods : Backend {
|
||||||
fn val_ty(v: Self::Value) -> Self::Type;
|
fn val_ty(&self, v: Self::Value) -> Self::Type;
|
||||||
fn c_bytes_in_context(llcx: Self::Context, bytes: &[u8]) -> Self::Value;
|
fn c_bytes_in_context(&self, llcx: Self::Context, bytes: &[u8]) -> Self::Value;
|
||||||
|
fn c_struct_in_context(
|
||||||
|
&self,
|
||||||
|
llcx: Self::Context,
|
||||||
|
elts: &[Self::Value],
|
||||||
|
packed: bool,
|
||||||
|
) -> Self::Value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,10 +68,15 @@ extern crate tempfile;
|
||||||
extern crate memmap;
|
extern crate memmap;
|
||||||
|
|
||||||
use back::bytecode::RLIB_BYTECODE_EXTENSION;
|
use back::bytecode::RLIB_BYTECODE_EXTENSION;
|
||||||
|
use interfaces::{Backend, CommonWriteMethods};
|
||||||
|
use value::Value;
|
||||||
|
use type_::Type;
|
||||||
|
|
||||||
pub use llvm_util::target_features;
|
pub use llvm_util::target_features;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use libc::{c_uint, c_char};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
|
||||||
use rustc::dep_graph::DepGraph;
|
use rustc::dep_graph::DepGraph;
|
||||||
|
@ -273,7 +278,7 @@ struct ModuleCodegen {
|
||||||
/// as the crate name and disambiguator.
|
/// as the crate name and disambiguator.
|
||||||
/// We currently generate these names via CodegenUnit::build_cgu_name().
|
/// We currently generate these names via CodegenUnit::build_cgu_name().
|
||||||
name: String,
|
name: String,
|
||||||
module_llvm: ModuleLlvm,
|
module_llvm: ModuleLlvm<'static>,
|
||||||
kind: ModuleKind,
|
kind: ModuleKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,16 +320,24 @@ impl ModuleCodegen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ModuleLlvm {
|
struct ModuleLlvm<'ll> {
|
||||||
llcx: &'static mut llvm::Context,
|
llcx: &'static mut llvm::Context,
|
||||||
llmod_raw: *const llvm::Module,
|
llmod_raw: *const llvm::Module,
|
||||||
tm: &'static mut llvm::TargetMachine,
|
tm: &'static mut llvm::TargetMachine,
|
||||||
|
phantom: PhantomData<&'ll ()>
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for ModuleLlvm { }
|
impl<'ll> Backend for ModuleLlvm<'ll> {
|
||||||
unsafe impl Sync for ModuleLlvm { }
|
type Value = &'ll Value;
|
||||||
|
type BasicBlock = &'ll llvm::BasicBlock;
|
||||||
|
type Type = &'ll Type;
|
||||||
|
type Context = &'ll llvm::Context;
|
||||||
|
}
|
||||||
|
|
||||||
impl ModuleLlvm {
|
unsafe impl Send for ModuleLlvm<'ll> { }
|
||||||
|
unsafe impl Sync for ModuleLlvm<'ll> { }
|
||||||
|
|
||||||
|
impl ModuleLlvm<'ll> {
|
||||||
fn new(sess: &Session, mod_name: &str) -> Self {
|
fn new(sess: &Session, mod_name: &str) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
|
let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
|
||||||
|
@ -334,6 +347,7 @@ impl ModuleLlvm {
|
||||||
llmod_raw,
|
llmod_raw,
|
||||||
llcx,
|
llcx,
|
||||||
tm: create_target_machine(sess, false),
|
tm: create_target_machine(sess, false),
|
||||||
|
phantom: PhantomData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,7 +359,39 @@ impl ModuleLlvm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ModuleLlvm {
|
impl CommonWriteMethods for ModuleLlvm<'ll> {
|
||||||
|
fn val_ty(&self, v: &'ll Value) -> &'ll Type {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMTypeOf(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
let ptr = bytes.as_ptr() as *const c_char;
|
||||||
|
return llvm::LLVMConstStringInContext(
|
||||||
|
llcx,
|
||||||
|
ptr,
|
||||||
|
bytes.len() as c_uint,
|
||||||
|
llvm::True);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_struct_in_context(
|
||||||
|
&self,
|
||||||
|
llcx: &'a llvm::Context,
|
||||||
|
elts: &[&'a Value],
|
||||||
|
packed: bool,
|
||||||
|
) -> &'a Value {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMConstStructInContext(llcx,
|
||||||
|
elts.as_ptr(), elts.len() as c_uint,
|
||||||
|
packed as llvm::Bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ModuleLlvm<'ll> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
|
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
|
||||||
|
|
|
@ -118,7 +118,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
|
|
||||||
// Use llvm.memset.p0i8.* to initialize byte arrays
|
// Use llvm.memset.p0i8.* to initialize byte arrays
|
||||||
let v = base::from_immediate(&bx, v);
|
let v = base::from_immediate(&bx, v);
|
||||||
if CodegenCx::val_ty(v) == Type::i8(bx.cx()) {
|
if bx.cx().val_ty(v) == Type::i8(bx.cx()) {
|
||||||
base::call_memset(&bx, start, v, size, align, false);
|
base::call_memset(&bx, start, v, size, align, false);
|
||||||
return bx;
|
return bx;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
let next_bx = bx.build_sibling_block("repeat_loop_next");
|
let next_bx = bx.build_sibling_block("repeat_loop_next");
|
||||||
|
|
||||||
bx.br(header_bx.llbb());
|
bx.br(header_bx.llbb());
|
||||||
let current = header_bx.phi(CodegenCx::val_ty(start), &[start], &[bx.llbb()]);
|
let current = header_bx.phi(bx.cx().val_ty(start), &[start], &[bx.llbb()]);
|
||||||
|
|
||||||
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
|
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
|
||||||
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
|
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
|
||||||
|
@ -705,8 +705,8 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
bx.extract_value(res, 1))
|
bx.extract_value(res, 1))
|
||||||
}
|
}
|
||||||
mir::BinOp::Shl | mir::BinOp::Shr => {
|
mir::BinOp::Shl | mir::BinOp::Shr => {
|
||||||
let lhs_llty = CodegenCx::val_ty(lhs);
|
let lhs_llty = bx.cx().val_ty(lhs);
|
||||||
let rhs_llty = CodegenCx::val_ty(rhs);
|
let rhs_llty = bx.cx().val_ty(rhs);
|
||||||
let invert_mask = common::shift_mask_val(&bx, lhs_llty, rhs_llty, true);
|
let invert_mask = common::shift_mask_val(&bx, lhs_llty, rhs_llty, true);
|
||||||
let outer_bits = bx.and(rhs, invert_mask);
|
let outer_bits = bx.and(rhs, invert_mask);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue