use rustc::session::Session;
use rustc::util::nodemap::FxHashMap;
use time_graph::{self, TimeGraph, Timeline};
-use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
+use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic, BasicBlock};
use llvm_util;
use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm,
CachedModuleCodegen};
use syntax_pos::symbol::Symbol;
use type_::Type;
use context::{is_pie_binary, get_reloc_model};
-use common::{C_bytes_in_context, val_ty};
+use interfaces::{Backend, CommonWriteMethods};
+use common;
use jobserver::{Client, Acquired};
use rustc_demangle;
+use value::Value;
+use std::marker::PhantomData;
use std::any::Any;
use std::ffi::{CString, CStr};
use std::thread;
use libc::{c_uint, c_void, c_char, size_t};
-pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [
+pub const RELOC_MODEL_ARGS : [(&str, llvm::RelocMode); 7] = [
("pic", llvm::RelocMode::PIC),
("static", llvm::RelocMode::Static),
("default", llvm::RelocMode::Default),
("large", llvm::CodeModel::Large),
];
-pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [
+pub const TLS_MODEL_ARGS : [(&str, llvm::ThreadLocalMode); 4] = [
("global-dynamic", llvm::ThreadLocalMode::GeneralDynamic),
("local-dynamic", llvm::ThreadLocalMode::LocalDynamic),
("initial-exec", llvm::ThreadLocalMode::InitialExec),
const PRE_THIN_LTO_BC_EXT: &str = "pre-thin-lto.bc";
-pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
+pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError {
match llvm::last_error() {
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
None => handler.fatal(&msg),
let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type);
if result.into_result().is_err() {
let msg = format!("could not write output to {}", output.display());
- Err(llvm_err(handler, msg))
+ Err(llvm_err(handler, &msg))
} else {
Ok(())
}
find_features: bool,
) -> &'static mut llvm::TargetMachine {
target_machine_factory(sess, find_features)().unwrap_or_else(|err| {
- llvm_err(sess.diagnostic(), err).raise()
+ llvm_err(sess.diagnostic(), &err).raise()
})
}
/// Additional resources used by optimize_and_codegen (not module specific)
#[derive(Clone)]
-pub struct CodegenContext {
+pub struct CodegenContext<'ll> {
// Resources needed when running LTO
pub time_passes: bool,
pub lto: Lto,
time_graph: Option<TimeGraph>,
// The assembler command if no_integrated_as option is enabled, None otherwise
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 {
Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
}
}
}
+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 {
+ common::val_ty(v)
+ }
+
+ fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
+ common::c_bytes_in_context(llcx, bytes)
+ }
+
+ fn c_struct_in_context(
+ &self,
+ llcx: &'a llvm::Context,
+ elts: &[&'a Value],
+ packed: bool,
+ ) -> &'a Value {
+ common::c_struct_in_context(llcx, elts, packed)
+ }
+}
+
+
pub struct DiagnosticHandlers<'a> {
- data: *mut (&'a CodegenContext, &'a Handler),
+ data: *mut (&'a CodegenContext<'a>, &'a Handler),
llcx: &'a llvm::Context,
}
impl<'a> DiagnosticHandlers<'a> {
- pub fn new(cgcx: &'a CodegenContext,
+ pub fn new(cgcx: &'a CodegenContext<'a>,
handler: &'a Handler,
llcx: &'a llvm::Context) -> Self {
let data = Box::into_raw(Box::new((cgcx, handler)));
unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext,
msg: &'b str,
cookie: c_uint) {
- cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string());
+ cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned());
}
unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic,
llcx: &llvm::Context,
llmod: &llvm::Module,
bitcode: Option<&[u8]>) {
- let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
+ let llconst = cgcx.c_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
let llglobal = llvm::LLVMAddGlobal(
llmod,
- val_ty(llconst),
+ cgcx.val_ty(llconst),
"rustc.embedded.module\0".as_ptr() as *const _,
);
llvm::LLVMSetInitializer(llglobal, llconst);
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
- let llconst = C_bytes_in_context(llcx, &[]);
+ let llconst = cgcx.c_bytes_in_context(llcx, &[]);
let llglobal = llvm::LLVMAddGlobal(
llmod,
- val_ty(llconst),
+ cgcx.val_ty(llconst),
"rustc.embedded.cmdline\0".as_ptr() as *const _,
);
llvm::LLVMSetInitializer(llglobal, llconst);
module.name,
source_file,
obj_out.display());
- match link_or_copy(&source_file, &obj_out) {
- Ok(_) => { }
- Err(err) => {
- let diag_handler = cgcx.create_diag_handler();
- diag_handler.err(&format!("unable to copy {} to {}: {}",
- source_file.display(),
- obj_out.display(),
- err));
- }
+ if let Err(err) = link_or_copy(&source_file, &obj_out) {
+ let diag_handler = cgcx.create_diag_handler();
+ diag_handler.err(&format!("unable to copy {} to {}: {}",
+ source_file.display(),
+ obj_out.display(),
+ err));
}
}
target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
debuginfo: tcx.sess.opts.debuginfo,
assembler_cmd,
+ phantom: PhantomData
};
// This is the "main loop" of parallel work happening for parallel codegen.
const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
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();
thread::spawn(move || {