use crate::context::{is_pie_binary, get_reloc_model};
use crate::common;
use crate::LlvmCodegenBackend;
+use rustc::bug;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler};
use rustc_codegen_ssa::traits::*;
-use rustc::session::config::{self, OutputType, Passes, Lto, SwitchWithOptPath};
+use rustc::session::config::{self, OutputType, Passes, Lto, Sanitizer, SwitchWithOptPath};
use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, CompiledModule};
use rustc::util::common::time_ext;
use rustc_fs_util::{path_to_c_string, link_or_copy};
use rustc_data_structures::small_c_str::SmallCStr;
-use errors::{Handler, FatalError};
+use rustc_errors::{Handler, FatalError};
+use log::debug;
-use std::ffi::{CString, CStr};
+use std::ffi::CString;
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::str;
use std::sync::Arc;
use std::slice;
-use libc::{c_uint, c_void, c_char, size_t};
+use libc::{c_int, c_uint, c_void, c_char, size_t};
pub const RELOC_MODEL_ARGS : [(&str, llvm::RelocMode); 7] = [
("pic", llvm::RelocMode::PIC),
("local-exec", llvm::ThreadLocalMode::LocalExec),
];
-pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError {
+pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
match llvm::last_error() {
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
None => handler.fatal(&msg),
}
pub fn write_output_file(
- handler: &errors::Handler,
+ handler: &rustc_errors::Handler,
target: &'ll llvm::TargetMachine,
pm: &llvm::PassManager<'ll>,
m: &'ll llvm::Module,
let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
let features = features.join(",");
let features = CString::new(features).unwrap();
+ let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname);
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();
-
+ let relax_elf_relocations = sess.target.target.options.relax_elf_relocations;
Arc::new(move || {
let tm = unsafe {
llvm::LLVMRustCreateTargetMachine(
- triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
+ triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), abi.as_ptr(),
code_model,
reloc_model,
opt_level,
singlethread,
asm_comments,
emit_stack_size_section,
+ relax_elf_relocations,
)
};
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
- if config.opt_level.is_some() {
+ if let Some(opt_level) = config.opt_level {
// Create the two optimizing pass managers. These mirror what clang
// does, and are by populated by LLVM's default PassManagerBuilder.
// Each manager has a different set of passes, but they also share
}
}
- for pass_name in &cgcx.plugin_passes {
- if let Some(pass) = find_pass(pass_name) {
- extra_passes.push(pass);
- } else {
- diag_handler.err(&format!("a plugin asked for LLVM pass \
- `{}` but LLVM does not \
- recognize it", pass_name));
- }
-
- if pass_name == "name-anon-globals" {
- have_name_anon_globals_pass = true;
- }
- }
+ add_sanitizer_passes(config, &mut extra_passes);
// Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
// to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
// we'll get errors in LLVM.
let using_thin_buffers = config.bitcode_needed();
if !config.no_prepopulate_passes {
- llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
- llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
- let opt_level = config.opt_level.map(|x| to_llvm_opt_settings(x).0)
- .unwrap_or(llvm::CodeGenOptLevel::None);
+ llvm::LLVMAddAnalysisPasses(tm, fpm);
+ llvm::LLVMAddAnalysisPasses(tm, mpm);
+ let opt_level = to_llvm_opt_settings(opt_level).0;
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal ||
(cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled());
with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
Ok(())
}
+unsafe fn add_sanitizer_passes(config: &ModuleConfig,
+ passes: &mut Vec<&'static mut llvm::Pass>) {
+
+ let sanitizer = match &config.sanitizer {
+ None => return,
+ Some(s) => s,
+ };
+
+ let recover = config.sanitizer_recover.contains(sanitizer);
+ match sanitizer {
+ Sanitizer::Address => {
+ passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover));
+ passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover));
+ }
+ Sanitizer::Memory => {
+ let track_origins = config.sanitizer_memory_track_origins as c_int;
+ passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover));
+ }
+ Sanitizer::Thread => {
+ passes.push(llvm::LLVMRustCreateThreadSanitizerPass());
+ }
+ Sanitizer::Leak => {}
+ }
+}
+
pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
diag_handler: &Handler,
module: ModuleCodegen<ModuleLlvm>,
where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
{
let cpm = llvm::LLVMCreatePassManager();
- llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
+ llvm::LLVMAddAnalysisPasses(tm, cpm);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
f(cpm)
}
cursor.position() as size_t
}
- with_codegen(tm, llmod, config.no_builtins, |cpm| {
- let result =
- llvm::LLVMRustPrintModule(cpm, llmod, out_c.as_ptr(), demangle_callback);
- llvm::LLVMDisposePassManager(cpm);
- result.into_result().map_err(|()| {
- let msg = format!("failed to write LLVM IR to {}", out.display());
- llvm_err(diag_handler, &msg)
- })
+ let result =
+ llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
+ result.into_result().map_err(|()| {
+ let msg = format!("failed to write LLVM IR to {}", out.display());
+ llvm_err(diag_handler, &msg)
})?;
}
})
.filter_map(|val| {
// Exclude some symbols that we know are not Rust symbols.
- let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
- if ignored(name.to_bytes()) {
+ let name = llvm::get_value_name(val);
+ if ignored(name) {
None
} else {
Some((val, name))
})
.map(move |(val, name)| {
let mut imp_name = prefix.as_bytes().to_vec();
- imp_name.extend(name.to_bytes());
+ imp_name.extend(name);
let imp_name = CString::new(imp_name).unwrap();
(imp_name, val)
})