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),
use back::write;
use errors::{FatalError, Handler};
use llvm::archive_ro::ArchiveRO;
-use llvm::{ModuleRef, TargetMachineRef, True, False};
+use llvm::{TargetMachineRef, True, False};
use llvm;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::middle::exported_symbols::SymbolExportLevel;
match *self {
LtoModuleCodegen::Fat { ref mut module, .. } => {
let module = module.take().unwrap();
- let config = cgcx.config(module.kind);
- let llmod = module.llvm().unwrap().llmod;
- let tm = module.llvm().unwrap().tm;
- run_pass_manager(cgcx, tm, llmod, config, false);
- timeline.record("fat-done");
+ {
+ let config = cgcx.config(module.kind);
+ let llmod = module.llvm().unwrap().llmod();
+ let tm = &*module.llvm().unwrap().tm;
+ run_pass_manager(cgcx, tm, llmod, config, false);
+ timeline.record("fat-done");
+ }
Ok(module)
}
LtoModuleCodegen::Thin(ref mut thin) => thin.optimize(cgcx, timeline),
.filter(|&(_, module)| module.kind == ModuleKind::Regular)
.map(|(i, module)| {
let cost = unsafe {
- llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod)
+ llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod())
};
(cost, i)
})
.max()
.expect("must be codegen'ing at least one module");
let module = modules.remove(costliest_module);
- let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod;
- info!("using {:?} as a base module", module.llmod_id);
-
- // For all other modules we codegened we'll need to link them into our own
- // bitcode. All modules were codegened in their own LLVM context, however,
- // and we want to move everything to the same LLVM context. Currently the
- // way we know of to do that is to serialize them to a string and them parse
- // them later. Not great but hey, that's why it's "fat" LTO, right?
- for module in modules {
- let llvm = module.llvm().expect("can't lto pre-codegened modules");
- let buffer = ModuleBuffer::new(llvm.llmod);
- let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
- serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
- }
-
- // For all serialized bitcode files we parse them and link them in as we did
- // above, this is all mostly handled in C++. Like above, though, we don't
- // know much about the memory management here so we err on the side of being
- // save and persist everything with the original module.
let mut serialized_bitcode = Vec::new();
- let mut linker = Linker::new(llmod);
- for (bc_decoded, name) in serialized_modules {
- info!("linking {:?}", name);
- time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || {
- let data = bc_decoded.data();
- linker.add(&data).map_err(|()| {
- let msg = format!("failed to load bc of {:?}", name);
- write::llvm_err(&diag_handler, msg)
- })
- })?;
- timeline.record(&format!("link {:?}", name));
- serialized_bitcode.push(bc_decoded);
- }
- drop(linker);
- cgcx.save_temp_bitcode(&module, "lto.input");
+ {
+ let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod();
+ info!("using {:?} as a base module", module.llmod_id);
+
+ // For all other modules we codegened we'll need to link them into our own
+ // bitcode. All modules were codegened in their own LLVM context, however,
+ // and we want to move everything to the same LLVM context. Currently the
+ // way we know of to do that is to serialize them to a string and them parse
+ // them later. Not great but hey, that's why it's "fat" LTO, right?
+ for module in modules {
+ let llvm = module.llvm().expect("can't lto pre-codegened modules");
+ let buffer = ModuleBuffer::new(llvm.llmod());
+ let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
+ serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
+ }
- // Internalize everything that *isn't* in our whitelist to help strip out
- // more modules and such
- unsafe {
- let ptr = symbol_white_list.as_ptr();
- llvm::LLVMRustRunRestrictionPass(llmod,
- ptr as *const *const libc::c_char,
- symbol_white_list.len() as libc::size_t);
- cgcx.save_temp_bitcode(&module, "lto.after-restriction");
- }
+ // For all serialized bitcode files we parse them and link them in as we did
+ // above, this is all mostly handled in C++. Like above, though, we don't
+ // know much about the memory management here so we err on the side of being
+ // save and persist everything with the original module.
+ let mut linker = Linker::new(llmod);
+ for (bc_decoded, name) in serialized_modules {
+ info!("linking {:?}", name);
+ time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || {
+ let data = bc_decoded.data();
+ linker.add(&data).map_err(|()| {
+ let msg = format!("failed to load bc of {:?}", name);
+ write::llvm_err(&diag_handler, msg)
+ })
+ })?;
+ timeline.record(&format!("link {:?}", name));
+ serialized_bitcode.push(bc_decoded);
+ }
+ drop(linker);
+ cgcx.save_temp_bitcode(&module, "lto.input");
- if cgcx.no_landing_pads {
+ // Internalize everything that *isn't* in our whitelist to help strip out
+ // more modules and such
unsafe {
- llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+ let ptr = symbol_white_list.as_ptr();
+ llvm::LLVMRustRunRestrictionPass(llmod,
+ ptr as *const *const libc::c_char,
+ symbol_white_list.len() as libc::size_t);
+ cgcx.save_temp_bitcode(&module, "lto.after-restriction");
}
- cgcx.save_temp_bitcode(&module, "lto.after-nounwind");
+
+ if cgcx.no_landing_pads {
+ unsafe {
+ llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+ }
+ cgcx.save_temp_bitcode(&module, "lto.after-nounwind");
+ }
+ timeline.record("passes");
}
- timeline.record("passes");
Ok(vec![LtoModuleCodegen::Fat {
module: Some(module),
struct Linker(llvm::LinkerRef);
impl Linker {
- fn new(llmod: ModuleRef) -> Linker {
+ fn new(llmod: &llvm::Module) -> Linker {
unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) }
}
info!("local module: {} - {}", i, module.llmod_id);
let llvm = module.llvm().expect("can't lto precodegened module");
let name = CString::new(module.llmod_id.clone()).unwrap();
- let buffer = ThinBuffer::new(llvm.llmod);
+ let buffer = ThinBuffer::new(llvm.llmod());
thin_modules.push(llvm::ThinLTOModule {
identifier: name.as_ptr(),
data: buffer.data().as_ptr(),
fn run_pass_manager(cgcx: &CodegenContext,
tm: TargetMachineRef,
- llmod: ModuleRef,
+ llmod: &llvm::Module,
config: &ModuleConfig,
thin: bool) {
// Now we have one massive module inside of llmod. Time to run the
unsafe impl Sync for ModuleBuffer {}
impl ModuleBuffer {
- pub fn new(m: ModuleRef) -> ModuleBuffer {
+ pub fn new(m: &llvm::Module) -> ModuleBuffer {
ModuleBuffer(unsafe {
llvm::LLVMRustModuleBufferCreate(m)
})
unsafe impl Sync for ThinBuffer {}
impl ThinBuffer {
- pub fn new(m: ModuleRef) -> ThinBuffer {
+ pub fn new(m: &llvm::Module) -> ThinBuffer {
unsafe {
let buffer = llvm::LLVMRustThinLTOBufferCreate(m);
ThinBuffer(buffer)
// crates but for locally codegened modules we may be able to reuse
// that LLVM Context and Module.
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
- let llmod = llvm::LLVMRustParseBitcodeForThinLTO(
+ let llmod_raw = llvm::LLVMRustParseBitcodeForThinLTO(
llcx,
self.data().as_ptr(),
self.data().len(),
self.shared.module_names[self.idx].as_ptr(),
- );
- if llmod.is_null() {
+ ).ok_or_else(|| {
let msg = "failed to parse bitcode for thin LTO module".to_string();
- return Err(write::llvm_err(&diag_handler, msg));
- }
+ write::llvm_err(&diag_handler, msg)
+ })? as *const _;
let module = ModuleCodegen {
source: ModuleSource::Codegened(ModuleLlvm {
- llmod,
+ llmod_raw,
llcx,
tm,
}),
name: self.name().to_string(),
kind: ModuleKind::Regular,
};
- cgcx.save_temp_bitcode(&module, "thin-lto-input");
-
- // Before we do much else find the "main" `DICompileUnit` that we'll be
- // using below. If we find more than one though then rustc has changed
- // in a way we're not ready for, so generate an ICE by returning
- // an error.
- let mut cu1 = ptr::null_mut();
- let mut cu2 = ptr::null_mut();
- llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
- if !cu2.is_null() {
- let msg = "multiple source DICompileUnits found".to_string();
- return Err(write::llvm_err(&diag_handler, msg))
- }
+ {
+ let llmod = module.llvm().unwrap().llmod();
+ cgcx.save_temp_bitcode(&module, "thin-lto-input");
+
+ // Before we do much else find the "main" `DICompileUnit` that we'll be
+ // using below. If we find more than one though then rustc has changed
+ // in a way we're not ready for, so generate an ICE by returning
+ // an error.
+ let mut cu1 = ptr::null_mut();
+ let mut cu2 = ptr::null_mut();
+ llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
+ if !cu2.is_null() {
+ let msg = "multiple source DICompileUnits found".to_string();
+ return Err(write::llvm_err(&diag_handler, msg))
+ }
- // Like with "fat" LTO, get some better optimizations if landing pads
- // are disabled by removing all landing pads.
- if cgcx.no_landing_pads {
- llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
- cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind");
- timeline.record("nounwind");
- }
+ // Like with "fat" LTO, get some better optimizations if landing pads
+ // are disabled by removing all landing pads.
+ if cgcx.no_landing_pads {
+ llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+ cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind");
+ timeline.record("nounwind");
+ }
- // Up next comes the per-module local analyses that we do for Thin LTO.
- // Each of these functions is basically copied from the LLVM
- // implementation and then tailored to suit this implementation. Ideally
- // each of these would be supported by upstream LLVM but that's perhaps
- // a patch for another day!
- //
- // You can find some more comments about these functions in the LLVM
- // bindings we've got (currently `PassWrapper.cpp`)
- if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module".to_string();
- return Err(write::llvm_err(&diag_handler, msg))
- }
- cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
- timeline.record("rename");
- if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module".to_string();
- return Err(write::llvm_err(&diag_handler, msg))
- }
- cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
- timeline.record("resolve");
- if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module".to_string();
- return Err(write::llvm_err(&diag_handler, msg))
- }
- cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
- timeline.record("internalize");
- if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module".to_string();
- return Err(write::llvm_err(&diag_handler, msg))
+ // Up next comes the per-module local analyses that we do for Thin LTO.
+ // Each of these functions is basically copied from the LLVM
+ // implementation and then tailored to suit this implementation. Ideally
+ // each of these would be supported by upstream LLVM but that's perhaps
+ // a patch for another day!
+ //
+ // You can find some more comments about these functions in the LLVM
+ // bindings we've got (currently `PassWrapper.cpp`)
+ if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
+ let msg = "failed to prepare thin LTO module".to_string();
+ return Err(write::llvm_err(&diag_handler, msg))
+ }
+ cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
+ timeline.record("rename");
+ if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
+ let msg = "failed to prepare thin LTO module".to_string();
+ return Err(write::llvm_err(&diag_handler, msg))
+ }
+ cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
+ timeline.record("resolve");
+ if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
+ let msg = "failed to prepare thin LTO module".to_string();
+ return Err(write::llvm_err(&diag_handler, msg))
+ }
+ cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
+ timeline.record("internalize");
+ if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
+ let msg = "failed to prepare thin LTO module".to_string();
+ return Err(write::llvm_err(&diag_handler, msg))
+ }
+ cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
+ timeline.record("import");
+
+ // Ok now this is a bit unfortunate. This is also something you won't
+ // find upstream in LLVM's ThinLTO passes! This is a hack for now to
+ // work around bugs in LLVM.
+ //
+ // First discovered in #45511 it was found that as part of ThinLTO
+ // importing passes LLVM will import `DICompileUnit` metadata
+ // information across modules. This means that we'll be working with one
+ // LLVM module that has multiple `DICompileUnit` instances in it (a
+ // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
+ // bugs in LLVM's backend which generates invalid DWARF in a situation
+ // like this:
+ //
+ // https://bugs.llvm.org/show_bug.cgi?id=35212
+ // https://bugs.llvm.org/show_bug.cgi?id=35562
+ //
+ // While the first bug there is fixed the second ended up causing #46346
+ // which was basically a resurgence of #45511 after LLVM's bug 35212 was
+ // fixed.
+ //
+ // This function below is a huge hack around this problem. The function
+ // below is defined in `PassWrapper.cpp` and will basically "merge"
+ // all `DICompileUnit` instances in a module. Basically it'll take all
+ // the objects, rewrite all pointers of `DISubprogram` to point to the
+ // first `DICompileUnit`, and then delete all the other units.
+ //
+ // This is probably mangling to the debug info slightly (but hopefully
+ // not too much) but for now at least gets LLVM to emit valid DWARF (or
+ // so it appears). Hopefully we can remove this once upstream bugs are
+ // fixed in LLVM.
+ llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
+ cgcx.save_temp_bitcode(&module, "thin-lto-after-patch");
+ timeline.record("patch");
+
+ // Alright now that we've done everything related to the ThinLTO
+ // analysis it's time to run some optimizations! Here we use the same
+ // `run_pass_manager` as the "fat" LTO above except that we tell it to
+ // populate a thin-specific pass manager, which presumably LLVM treats a
+ // little differently.
+ info!("running thin lto passes over {}", module.name);
+ let config = cgcx.config(module.kind);
+ run_pass_manager(cgcx, module.llvm().unwrap().tm, llmod, config, true);
+ cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
+ timeline.record("thin-done");
}
- cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
- timeline.record("import");
-
- // Ok now this is a bit unfortunate. This is also something you won't
- // find upstream in LLVM's ThinLTO passes! This is a hack for now to
- // work around bugs in LLVM.
- //
- // First discovered in #45511 it was found that as part of ThinLTO
- // importing passes LLVM will import `DICompileUnit` metadata
- // information across modules. This means that we'll be working with one
- // LLVM module that has multiple `DICompileUnit` instances in it (a
- // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
- // bugs in LLVM's backend which generates invalid DWARF in a situation
- // like this:
- //
- // https://bugs.llvm.org/show_bug.cgi?id=35212
- // https://bugs.llvm.org/show_bug.cgi?id=35562
- //
- // While the first bug there is fixed the second ended up causing #46346
- // which was basically a resurgence of #45511 after LLVM's bug 35212 was
- // fixed.
- //
- // This function below is a huge hack around this problem. The function
- // below is defined in `PassWrapper.cpp` and will basically "merge"
- // all `DICompileUnit` instances in a module. Basically it'll take all
- // the objects, rewrite all pointers of `DISubprogram` to point to the
- // first `DICompileUnit`, and then delete all the other units.
- //
- // This is probably mangling to the debug info slightly (but hopefully
- // not too much) but for now at least gets LLVM to emit valid DWARF (or
- // so it appears). Hopefully we can remove this once upstream bugs are
- // fixed in LLVM.
- llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
- cgcx.save_temp_bitcode(&module, "thin-lto-after-patch");
- timeline.record("patch");
-
- // Alright now that we've done everything related to the ThinLTO
- // analysis it's time to run some optimizations! Here we use the same
- // `run_pass_manager` as the "fat" LTO above except that we tell it to
- // populate a thin-specific pass manager, which presumably LLVM treats a
- // little differently.
- info!("running thin lto passes over {}", module.name);
- let config = cgcx.config(module.kind);
- run_pass_manager(cgcx, tm, llmod, config, true);
- cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
- timeline.record("thin-done");
Ok(module)
}
use rustc::util::nodemap::FxHashMap;
use time_graph::{self, TimeGraph, Timeline};
use llvm;
-use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
-use llvm::{SMDiagnosticRef, ContextRef};
+use llvm::{TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
+use llvm::SMDiagnosticRef;
use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind};
use CrateInfo;
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
handler: &errors::Handler,
target: llvm::TargetMachineRef,
pm: llvm::PassManagerRef,
- m: ModuleRef,
+ m: &llvm::Module,
output: &Path,
file_type: llvm::FileType) -> Result<(), FatalError> {
unsafe {
}
}
-pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachineRef {
+pub fn create_target_machine(sess: &Session, find_features: bool) -> &'static mut llvm::TargetMachine {
target_machine_factory(sess, find_features)().unwrap_or_else(|err| {
llvm_err(sess.diagnostic(), err).raise()
})
// that `is_pie_binary` is false. When we discover LLVM target features
// `sess.crate_types` is uninitialized so we cannot access it.
pub fn target_machine_factory(sess: &Session, find_features: bool)
- -> Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync>
+ -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync>
{
let reloc_model = get_reloc_model(sess);
)
};
- if tm.is_null() {
- Err(format!("Could not create LLVM TargetMachine for triple: {}",
- triple.to_str().unwrap()))
- } else {
- Ok(tm)
- }
+ tm.ok_or_else(|| {
+ format!("Could not create LLVM TargetMachine for triple: {}",
+ triple.to_str().unwrap())
+ })
})
}
regular_module_config: Arc<ModuleConfig>,
metadata_module_config: Arc<ModuleConfig>,
allocator_module_config: Arc<ModuleConfig>,
- pub tm_factory: Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync>,
+ pub tm_factory: Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync>,
pub msvc_imps_needed: bool,
pub target_pointer_width: String,
debuginfo: config::DebugInfoLevel,
let cgu = Some(&module.name[..]);
let path = self.output_filenames.temp_path_ext(&ext, cgu);
let cstr = path2cstr(&path);
- let llmod = module.llvm().unwrap().llmod;
+ let llmod = module.llvm().unwrap().llmod();
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
}
}
struct DiagnosticHandlers<'a> {
data: *mut (&'a CodegenContext, &'a Handler),
- llcx: ContextRef,
+ llcx: &'a llvm::Context,
}
impl<'a> DiagnosticHandlers<'a> {
fn new(cgcx: &'a CodegenContext,
handler: &'a Handler,
- llcx: ContextRef) -> DiagnosticHandlers<'a> {
+ llcx: &'a llvm::Context) -> Self {
let data = Box::into_raw(Box::new((cgcx, handler)));
unsafe {
llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _);
-> Result<(), FatalError>
{
let (llmod, llcx, tm) = match module.source {
- ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
+ ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
ModuleSource::Preexisting(_) => {
bug!("optimize_and_codegen: called with ModuleSource::Preexisting")
}
-> Result<CompiledModule, FatalError>
{
timeline.record("codegen");
- let (llmod, llcx, tm) = match module.source {
- ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
- ModuleSource::Preexisting(_) => {
- bug!("codegen: called with ModuleSource::Preexisting")
- }
- };
- let module_name = module.name.clone();
- let module_name = Some(&module_name[..]);
- let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
-
- if cgcx.msvc_imps_needed {
- create_msvc_imps(cgcx, llcx, llmod);
- }
-
- // A codegen-specific pass manager is used to generate object
- // files for an LLVM module.
- //
- // Apparently each of these pass managers is a one-shot kind of
- // thing, so we create a new one for each type of output. The
- // pass manager passed to the closure should be ensured to not
- // escape the closure itself, and the manager should only be
- // used once.
- unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
- llmod: ModuleRef,
- no_builtins: bool,
- f: F) -> R
- where F: FnOnce(PassManagerRef) -> R,
{
- let cpm = llvm::LLVMCreatePassManager();
- llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
- llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
- f(cpm)
- }
-
- // If we don't have the integrated assembler, then we need to emit asm
- // from LLVM and use `gcc` to create the object file.
- let asm_to_obj = config.emit_obj && config.no_integrated_as;
-
- // Change what we write and cleanup based on whether obj files are
- // just llvm bitcode. In that case write bitcode, and possibly
- // delete the bitcode if it wasn't requested. Don't generate the
- // machine code, instead copy the .o file from the .bc
- let write_bc = config.emit_bc || config.obj_is_bitcode;
- let rm_bc = !config.emit_bc && config.obj_is_bitcode;
- let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
- let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
-
- let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
- let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
-
-
- if write_bc || config.emit_bc_compressed || config.embed_bitcode {
- let thin;
- let old;
- let data = if llvm::LLVMRustThinLTOAvailable() {
- thin = ThinBuffer::new(llmod);
- thin.data()
- } else {
- old = ModuleBuffer::new(llmod);
- old.data()
+ let (llmod, llcx, tm) = match module.source {
+ ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
+ ModuleSource::Preexisting(_) => {
+ bug!("codegen: called with ModuleSource::Preexisting")
+ }
};
- timeline.record("make-bc");
+ let module_name = module.name.clone();
+ let module_name = Some(&module_name[..]);
+ let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
- if write_bc {
- if let Err(e) = fs::write(&bc_out, data) {
- diag_handler.err(&format!("failed to write bytecode: {}", e));
- }
- timeline.record("write-bc");
+ if cgcx.msvc_imps_needed {
+ create_msvc_imps(cgcx, llcx, llmod);
}
- if config.embed_bitcode {
- embed_bitcode(cgcx, llcx, llmod, Some(data));
- timeline.record("embed-bc");
- }
+ // A codegen-specific pass manager is used to generate object
+ // files for an LLVM module.
+ //
+ // Apparently each of these pass managers is a one-shot kind of
+ // thing, so we create a new one for each type of output. The
+ // pass manager passed to the closure should be ensured to not
+ // escape the closure itself, and the manager should only be
+ // used once.
+ unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
+ llmod: &llvm::Module,
+ no_builtins: bool,
+ f: F) -> R
+ where F: FnOnce(PassManagerRef) -> R,
+ {
+ let cpm = llvm::LLVMCreatePassManager();
+ llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
+ llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
+ f(cpm)
+ }
+
+ // If we don't have the integrated assembler, then we need to emit asm
+ // from LLVM and use `gcc` to create the object file.
+ let asm_to_obj = config.emit_obj && config.no_integrated_as;
+
+ // Change what we write and cleanup based on whether obj files are
+ // just llvm bitcode. In that case write bitcode, and possibly
+ // delete the bitcode if it wasn't requested. Don't generate the
+ // machine code, instead copy the .o file from the .bc
+ let write_bc = config.emit_bc || config.obj_is_bitcode;
+ let rm_bc = !config.emit_bc && config.obj_is_bitcode;
+ let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
+ let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
+
+ let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
+ let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
+
+
+ if write_bc || config.emit_bc_compressed || config.embed_bitcode {
+ let thin;
+ let old;
+ let data = if llvm::LLVMRustThinLTOAvailable() {
+ thin = ThinBuffer::new(llmod);
+ thin.data()
+ } else {
+ old = ModuleBuffer::new(llmod);
+ old.data()
+ };
+ timeline.record("make-bc");
- if config.emit_bc_compressed {
- let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
- let data = bytecode::encode(&module.llmod_id, data);
- if let Err(e) = fs::write(&dst, data) {
- diag_handler.err(&format!("failed to write bytecode: {}", e));
+ if write_bc {
+ if let Err(e) = fs::write(&bc_out, data) {
+ diag_handler.err(&format!("failed to write bytecode: {}", e));
+ }
+ timeline.record("write-bc");
}
- timeline.record("compress-bc");
- }
- } else if config.embed_bitcode_marker {
- embed_bitcode(cgcx, llcx, llmod, None);
- }
- time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
- || -> Result<(), FatalError> {
- if config.emit_ir {
- let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
- let out = path2cstr(&out);
-
- extern "C" fn demangle_callback(input_ptr: *const c_char,
- input_len: size_t,
- output_ptr: *mut c_char,
- output_len: size_t) -> size_t {
- let input = unsafe {
- slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
- };
+ if config.embed_bitcode {
+ embed_bitcode(cgcx, llcx, llmod, Some(data));
+ timeline.record("embed-bc");
+ }
- let input = match str::from_utf8(input) {
- Ok(s) => s,
- Err(_) => return 0,
- };
+ if config.emit_bc_compressed {
+ let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
+ let data = bytecode::encode(&module.llmod_id, data);
+ if let Err(e) = fs::write(&dst, data) {
+ diag_handler.err(&format!("failed to write bytecode: {}", e));
+ }
+ timeline.record("compress-bc");
+ }
+ } else if config.embed_bitcode_marker {
+ embed_bitcode(cgcx, llcx, llmod, None);
+ }
+
+ time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
+ || -> Result<(), FatalError> {
+ if config.emit_ir {
+ let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
+ let out = path2cstr(&out);
+
+ extern "C" fn demangle_callback(input_ptr: *const c_char,
+ input_len: size_t,
+ output_ptr: *mut c_char,
+ output_len: size_t) -> size_t {
+ let input = unsafe {
+ slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
+ };
- let output = unsafe {
- slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
- };
- let mut cursor = io::Cursor::new(output);
+ let input = match str::from_utf8(input) {
+ Ok(s) => s,
+ Err(_) => return 0,
+ };
- let demangled = match rustc_demangle::try_demangle(input) {
- Ok(d) => d,
- Err(_) => return 0,
- };
+ let output = unsafe {
+ slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
+ };
+ let mut cursor = io::Cursor::new(output);
+
+ let demangled = match rustc_demangle::try_demangle(input) {
+ Ok(d) => d,
+ Err(_) => return 0,
+ };
- if let Err(_) = write!(cursor, "{:#}", demangled) {
- // Possible only if provided buffer is not big enough
- return 0;
+ if let Err(_) = write!(cursor, "{:#}", demangled) {
+ // Possible only if provided buffer is not big enough
+ return 0;
+ }
+
+ cursor.position() as size_t
}
- cursor.position() as size_t
+ with_codegen(tm, llmod, config.no_builtins, |cpm| {
+ llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
+ llvm::LLVMDisposePassManager(cpm);
+ });
+ timeline.record("ir");
}
- with_codegen(tm, llmod, config.no_builtins, |cpm| {
- llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
- llvm::LLVMDisposePassManager(cpm);
- });
- timeline.record("ir");
- }
+ if config.emit_asm || asm_to_obj {
+ let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
- if config.emit_asm || asm_to_obj {
- let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
-
- // We can't use the same module for asm and binary output, because that triggers
- // various errors like invalid IR or broken binaries, so we might have to clone the
- // module to produce the asm output
- let llmod = if config.emit_obj {
- llvm::LLVMCloneModule(llmod)
- } else {
- llmod
- };
- with_codegen(tm, llmod, config.no_builtins, |cpm| {
- write_output_file(diag_handler, tm, cpm, llmod, &path,
- llvm::FileType::AssemblyFile)
- })?;
- if config.emit_obj {
- llvm::LLVMDisposeModule(llmod);
+ // We can't use the same module for asm and binary output, because that triggers
+ // various errors like invalid IR or broken binaries, so we might have to clone the
+ // module to produce the asm output
+ let llmod = if config.emit_obj {
+ llvm::LLVMCloneModule(llmod)
+ } else {
+ llmod
+ };
+ with_codegen(tm, llmod, config.no_builtins, |cpm| {
+ write_output_file(diag_handler, tm, cpm, llmod, &path,
+ llvm::FileType::AssemblyFile)
+ })?;
+ timeline.record("asm");
}
- timeline.record("asm");
- }
- if write_obj {
- with_codegen(tm, llmod, config.no_builtins, |cpm| {
- write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
- llvm::FileType::ObjectFile)
- })?;
- timeline.record("obj");
- } else if asm_to_obj {
- let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
- run_assembler(cgcx, diag_handler, &assembly, &obj_out);
- timeline.record("asm_to_obj");
-
- if !config.emit_asm && !cgcx.save_temps {
- drop(fs::remove_file(&assembly));
+ if write_obj {
+ with_codegen(tm, llmod, config.no_builtins, |cpm| {
+ write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
+ llvm::FileType::ObjectFile)
+ })?;
+ timeline.record("obj");
+ } else if asm_to_obj {
+ let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+ run_assembler(cgcx, diag_handler, &assembly, &obj_out);
+ timeline.record("asm_to_obj");
+
+ if !config.emit_asm && !cgcx.save_temps {
+ drop(fs::remove_file(&assembly));
+ }
}
- }
- Ok(())
- })?;
+ Ok(())
+ })?;
- if copy_bc_to_obj {
- debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
- if let Err(e) = link_or_copy(&bc_out, &obj_out) {
- diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+ if copy_bc_to_obj {
+ debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
+ if let Err(e) = link_or_copy(&bc_out, &obj_out) {
+ diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+ }
}
- }
- if rm_bc {
- debug!("removing_bitcode {:?}", bc_out);
- if let Err(e) = fs::remove_file(&bc_out) {
- diag_handler.err(&format!("failed to remove bitcode: {}", e));
+ if rm_bc {
+ debug!("removing_bitcode {:?}", bc_out);
+ if let Err(e) = fs::remove_file(&bc_out) {
+ diag_handler.err(&format!("failed to remove bitcode: {}", e));
+ }
}
- }
- drop(handlers);
+ drop(handlers);
+ }
Ok(module.into_compiled_module(config.emit_obj,
config.emit_bc,
config.emit_bc_compressed,
/// Basically all of this is us attempting to follow in the footsteps of clang
/// on iOS. See #35968 for lots more info.
unsafe fn embed_bitcode(cgcx: &CodegenContext,
- llcx: ContextRef,
- llmod: ModuleRef,
+ llcx: &llvm::Context,
+ llmod: &llvm::Module,
bitcode: Option<&[u8]>) {
let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
let llglobal = llvm::LLVMAddGlobal(
}
}
-pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
+pub unsafe fn with_llvm_pmb(llmod: &llvm::Module,
config: &ModuleConfig,
opt_level: llvm::CodeGenOptLevel,
prepare_for_thin_lto: bool,
// when using MSVC linker. We do this only for data, as linker can fix up
// code references on its own.
// See #26591, #27438
-fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) {
+fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) {
if !cgcx.msvc_imps_needed {
return
}
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};
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;
use std::any::Any;
use std::ffi::CString;
-use std::str;
use std::sync::Arc;
use std::time::{Instant, Duration};
use std::i32;
}
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 {
}).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);
let directive = CString::new(directive).unwrap();
llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
}
- return (metadata_llcx, metadata_llmod, metadata);
+ return metadata;
}
pub struct ValueIter {
}
}
-pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
+pub fn iter_globals(llmod: &llvm::Module) -> ValueIter {
unsafe {
ValueIter {
cur: llvm::LLVMGetFirstGlobal(llmod),
// 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,
};
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)
});
.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 {
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,
+ })
}
}
//! 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;
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,
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);
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;
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>>,
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>>,
!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);
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`
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),
+ }
}
}
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,
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};
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>>,
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
#[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()
}
#![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)]
#![feature(link_args)]
#![feature(static_nobundle)]
+use back::write::create_target_machine;
use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol;
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 _));
}
}
}
}
// Opaque pointer types
-extern { pub type Module_opaque; }
-pub type ModuleRef = *mut Module_opaque;
-extern { pub type Context_opaque; }
-pub type ContextRef = *mut Context_opaque;
+extern { pub type Module; }
+extern { pub type Context; }
extern { pub type Type_opaque; }
pub type TypeRef = *mut Type_opaque;
extern { pub type Value_opaque; }
pub type SectionIteratorRef = *mut SectionIterator_opaque;
extern { pub type Pass_opaque; }
pub type PassRef = *mut Pass_opaque;
-extern { pub type TargetMachine_opaque; }
-pub type TargetMachineRef = *mut TargetMachine_opaque;
+extern { pub type TargetMachine; }
+pub type TargetMachineRef = *const TargetMachine;
extern { pub type Archive_opaque; }
pub type ArchiveRef = *mut Archive_opaque;
extern { pub type ArchiveIterator_opaque; }
#[allow(improper_ctypes)] // TODO remove this (use for NonNull)
extern "C" {
// Create and destroy contexts.
- pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef;
- pub fn LLVMContextDispose(C: ContextRef);
- pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint;
+ pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;
+ pub fn LLVMContextDispose(C: &'static mut Context);
+ pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint;
- // Create and destroy modules.
- pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: ContextRef) -> ModuleRef;
- pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
- pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
- pub fn LLVMDisposeModule(M: ModuleRef);
+ // Create modules.
+ pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: &Context) -> &Module;
+ pub fn LLVMGetModuleContext(M: &Module) -> &Context;
+ pub fn LLVMCloneModule(M: &Module) -> &Module;
/// Data layout. See Module::getDataLayout.
- pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
- pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
+ pub fn LLVMGetDataLayout(M: &Module) -> *const c_char;
+ pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
/// See Module::dump.
- pub fn LLVMDumpModule(M: ModuleRef);
+ pub fn LLVMDumpModule(M: &Module);
/// See Module::setModuleInlineAsm.
- pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
- pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
+ pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char);
+ pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char);
/// See llvm::LLVMTypeKind::getTypeID.
pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
// Operations on integer types
- pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef;
+ pub fn LLVMInt1TypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMInt8TypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMInt16TypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMInt32TypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMInt64TypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> TypeRef;
pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
// Operations on real types
- pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMFloatTypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMDoubleTypeInContext(C: &Context) -> TypeRef;
// Operations on function types
pub fn LLVMFunctionType(ReturnType: TypeRef,
pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
// Operations on struct types
- pub fn LLVMStructTypeInContext(C: ContextRef,
+ pub fn LLVMStructTypeInContext(C: &Context,
ElementTypes: *const TypeRef,
ElementCount: c_uint,
Packed: Bool)
pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
// Operations on other types
- pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMX86MMXTypeInContext(C: ContextRef) -> TypeRef;
- pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef;
+ pub fn LLVMVoidTypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMX86MMXTypeInContext(C: &Context) -> TypeRef;
+ pub fn LLVMRustMetadataTypeInContext(C: &Context) -> TypeRef;
// Operations on all values
pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
// Operations on metadata
- pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef;
- pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef;
- pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef);
+ pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> ValueRef;
+ pub fn LLVMMDNodeInContext(C: &Context, Vals: *const ValueRef, Count: c_uint) -> ValueRef;
+ pub fn LLVMAddNamedMetadataOperand(M: &Module, Name: *const c_char, Val: ValueRef);
// Operations on scalar constants
pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef;
// Operations on composite constants
- pub fn LLVMConstStringInContext(C: ContextRef,
+ pub fn LLVMConstStringInContext(C: &Context,
Str: *const c_char,
Length: c_uint,
DontNullTerminate: Bool)
-> ValueRef;
- pub fn LLVMConstStructInContext(C: ContextRef,
+ pub fn LLVMConstStructInContext(C: &Context,
ConstantVals: *const ValueRef,
Count: c_uint,
Packed: Bool)
// Operations on global variables, functions, and aliases (globals)
- pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage;
pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage);
// Operations on global variables
pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef;
- pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char) -> ValueRef;
- pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef;
- pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef;
- pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
+ pub fn LLVMAddGlobal(M: &Module, Ty: TypeRef, Name: *const c_char) -> ValueRef;
+ pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> ValueRef;
+ pub fn LLVMRustGetOrInsertGlobal(M: &Module, Name: *const c_char, T: TypeRef) -> ValueRef;
+ pub fn LLVMGetFirstGlobal(M: &Module) -> ValueRef;
pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
pub fn LLVMDeleteGlobal(GlobalVar: ValueRef);
pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode);
pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
- pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
+ pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> ValueRef;
pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
// Operations on functions
- pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef;
- pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
- pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
+ pub fn LLVMAddFunction(M: &Module, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef;
+ pub fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> ValueRef;
+ pub fn LLVMGetFirstFunction(M: &Module) -> ValueRef;
pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
- pub fn LLVMRustGetOrInsertFunction(M: ModuleRef,
+ pub fn LLVMRustGetOrInsertFunction(M: &Module,
Name: *const c_char,
FunctionTy: TypeRef)
-> ValueRef;
// Operations on basic blocks
pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
- pub fn LLVMAppendBasicBlockInContext(C: ContextRef,
+ pub fn LLVMAppendBasicBlockInContext(C: &Context,
Fn: ValueRef,
Name: *const c_char)
-> BasicBlockRef;
Count: c_uint);
// Instruction builders
- pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
+ pub fn LLVMCreateBuilderInContext(C: &Context) -> BuilderRef;
pub fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef);
pub fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef);
pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef);
pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
/// Writes a module to the specified path. Returns 0 on success.
- pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
+ pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
/// Creates target data from a target layout string.
pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
pub fn LLVMCreatePassManager() -> PassManagerRef;
/// Creates a function-by-function pass manager
- pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef) -> PassManagerRef;
+ pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> PassManagerRef;
/// Disposes a pass manager.
pub fn LLVMDisposePassManager(PM: PassManagerRef);
/// Runs a pass manager on a module.
- pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
+ pub fn LLVMRunPassManager(PM: PassManagerRef, M: &Module) -> Bool;
pub fn LLVMInitializePasses();
/// Print the pass timings since static dtors aren't picking them up.
pub fn LLVMRustPrintPassTimings();
- pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef;
+ pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> TypeRef;
pub fn LLVMStructSetBody(StructTy: TypeRef,
ElementTypes: *const TypeRef,
pub fn LLVMRustVersionMajor() -> u32;
pub fn LLVMRustVersionMinor() -> u32;
- pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32);
+ pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
- pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef;
+ pub fn LLVMRustMetadataAsValue(C: &Context, MD: MetadataRef) -> ValueRef;
- pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
+ pub fn LLVMRustDIBuilderCreate(M: &Module) -> DIBuilderRef;
pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef);
TypeArray: DIArray);
- pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
+ pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &Context,
Line: c_uint,
Column: c_uint,
Scope: DIScope,
DataSections: bool,
TrapUnreachable: bool,
Singlethread: bool)
- -> TargetMachineRef;
- pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
- pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef);
+ -> Option<&'static mut TargetMachine>;
+ pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
+ pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: &Module);
pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
- M: ModuleRef,
+ M: &Module,
DisableSimplifyLibCalls: bool);
pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
OptLevel: CodeGenOptLevel,
PGOGenPath: *const c_char,
PGOUsePath: *const c_char);
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef,
- M: ModuleRef,
+ M: &Module,
DisableSimplifyLibCalls: bool);
- pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
+ pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: &Module);
pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
PM: PassManagerRef,
- M: ModuleRef,
+ M: &Module,
Output: *const c_char,
FileType: FileType)
-> LLVMRustResult;
pub fn LLVMRustPrintModule(PM: PassManagerRef,
- M: ModuleRef,
+ M: &Module,
Output: *const c_char,
Demangle: extern fn(*const c_char,
size_t,
size_t) -> size_t);
pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
pub fn LLVMRustPrintPasses();
- pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
+ pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool);
- pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t);
- pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
+ pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
+ pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module);
pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef);
- pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
+ pub fn LLVMContextSetDiagnosticHandler(C: &Context,
Handler: DiagnosticHandler,
DiagnosticContext: *mut c_void);
pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
- pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
+ pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: &Context,
H: InlineAsmDiagHandler,
CX: *mut c_void);
-> RustArchiveMemberRef;
pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
- pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef);
+ pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &Module, TM: TargetMachineRef);
pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
Inputs: *const ValueRef,
pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
- pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
+ pub fn LLVMRustSetComdat(M: &Module, V: ValueRef, Name: *const c_char);
pub fn LLVMRustUnsetComdat(V: ValueRef);
- pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
- pub fn LLVMRustModuleBufferCreate(M: ModuleRef) -> *mut ModuleBuffer;
+ pub fn LLVMRustSetModulePIELevel(M: &Module);
+ pub fn LLVMRustModuleBufferCreate(M: &Module) -> *mut ModuleBuffer;
pub fn LLVMRustModuleBufferPtr(p: *const ModuleBuffer) -> *const u8;
pub fn LLVMRustModuleBufferLen(p: *const ModuleBuffer) -> usize;
pub fn LLVMRustModuleBufferFree(p: *mut ModuleBuffer);
- pub fn LLVMRustModuleCost(M: ModuleRef) -> u64;
+ pub fn LLVMRustModuleCost(M: &Module) -> u64;
pub fn LLVMRustThinLTOAvailable() -> bool;
pub fn LLVMRustPGOAvailable() -> bool;
pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef,
- M: ModuleRef,
+ M: &Module,
BC: *const c_char) -> bool;
- pub fn LLVMRustThinLTOBufferCreate(M: ModuleRef) -> *mut ThinLTOBuffer;
+ pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> *mut ThinLTOBuffer;
pub fn LLVMRustThinLTOBufferFree(M: *mut ThinLTOBuffer);
pub fn LLVMRustThinLTOBufferPtr(M: *const ThinLTOBuffer) -> *const c_char;
pub fn LLVMRustThinLTOBufferLen(M: *const ThinLTOBuffer) -> size_t;
) -> *mut ThinLTOData;
pub fn LLVMRustPrepareThinLTORename(
Data: *const ThinLTOData,
- Module: ModuleRef,
+ Module: &Module,
) -> bool;
pub fn LLVMRustPrepareThinLTOResolveWeak(
Data: *const ThinLTOData,
- Module: ModuleRef,
+ Module: &Module,
) -> bool;
pub fn LLVMRustPrepareThinLTOInternalize(
Data: *const ThinLTOData,
- Module: ModuleRef,
+ Module: &Module,
) -> bool;
pub fn LLVMRustPrepareThinLTOImport(
Data: *const ThinLTOData,
- Module: ModuleRef,
+ Module: &Module,
) -> bool;
pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData);
pub fn LLVMRustParseBitcodeForThinLTO(
- Context: ContextRef,
+ Context: &Context,
Data: *const u8,
len: usize,
Identifier: *const c_char,
- ) -> ModuleRef;
- pub fn LLVMGetModuleIdentifier(M: ModuleRef, size: *mut usize) -> *const c_char;
- pub fn LLVMRustThinLTOGetDICompileUnit(M: ModuleRef,
+ ) -> Option<&Module>;
+ pub fn LLVMGetModuleIdentifier(M: &Module, size: *mut usize) -> *const c_char;
+ pub fn LLVMRustThinLTOGetDICompileUnit(M: &Module,
CU1: *mut *mut c_void,
CU2: *mut *mut c_void);
- pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void);
+ pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
- pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef;
+ pub fn LLVMRustLinkerNew(M: &Module) -> LinkerRef;
pub fn LLVMRustLinkerAdd(linker: LinkerRef,
bytecode: *const c_char,
bytecode_len: usize) -> bool;
// 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));
}
#![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;
ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
}
- pub fn i8_llcx(llcx: ContextRef) -> Type {
+ pub fn i8_llcx(llcx: &llvm::Context) -> Type {
ty!(llvm::LLVMInt8TypeInContext(llcx))
}
}
// 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))
}
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()
}