rustc_codegen_llvm: use safe references for Context and Module.
This commit is contained in:
parent
af04e9426c
commit
249d5acaec
13 changed files with 546 additions and 553 deletions
|
@ -20,8 +20,8 @@ use ModuleLlvm;
|
|||
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),
|
||||
|
|
|
@ -14,7 +14,7 @@ use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext};
|
|||
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;
|
||||
|
@ -73,11 +73,13 @@ impl LtoModuleCodegen {
|
|||
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),
|
||||
|
@ -223,66 +225,68 @@ fn fat_lto(cgcx: &CodegenContext,
|
|||
.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);
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
if cgcx.no_landing_pads {
|
||||
unsafe {
|
||||
llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
|
||||
// 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));
|
||||
}
|
||||
cgcx.save_temp_bitcode(&module, "lto.after-nounwind");
|
||||
|
||||
// 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");
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
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),
|
||||
|
@ -293,7 +297,7 @@ fn fat_lto(cgcx: &CodegenContext,
|
|||
struct Linker(llvm::LinkerRef);
|
||||
|
||||
impl Linker {
|
||||
fn new(llmod: ModuleRef) -> Linker {
|
||||
fn new(llmod: &llvm::Module) -> Linker {
|
||||
unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) }
|
||||
}
|
||||
|
||||
|
@ -371,7 +375,7 @@ fn thin_lto(diag_handler: &Handler,
|
|||
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(),
|
||||
|
@ -449,7 +453,7 @@ fn thin_lto(diag_handler: &Handler,
|
|||
|
||||
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
|
||||
|
@ -531,7 +535,7 @@ unsafe impl Send for ModuleBuffer {}
|
|||
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)
|
||||
})
|
||||
|
@ -583,7 +587,7 @@ unsafe impl Send for ThinBuffer {}
|
|||
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)
|
||||
|
@ -640,19 +644,18 @@ impl ThinModule {
|
|||
// 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,
|
||||
}),
|
||||
|
@ -660,104 +663,107 @@ impl ThinModule {
|
|||
name: self.name().to_string(),
|
||||
kind: ModuleKind::Regular,
|
||||
};
|
||||
cgcx.save_temp_bitcode(&module, "thin-lto-input");
|
||||
{
|
||||
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))
|
||||
}
|
||||
// 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))
|
||||
}
|
||||
cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
|
||||
timeline.record("import");
|
||||
// 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");
|
||||
// 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");
|
||||
// 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");
|
||||
}
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ use rustc::session::Session;
|
|||
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};
|
||||
|
@ -96,7 +96,7 @@ pub fn write_output_file(
|
|||
handler: &errors::Handler,
|
||||
target: llvm::TargetMachineRef,
|
||||
pm: llvm::PassManagerRef,
|
||||
m: ModuleRef,
|
||||
m: &llvm::Module,
|
||||
output: &Path,
|
||||
file_type: llvm::FileType) -> Result<(), FatalError> {
|
||||
unsafe {
|
||||
|
@ -130,7 +130,7 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
|
|||
}
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
|
@ -140,7 +140,7 @@ pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachi
|
|||
// 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);
|
||||
|
||||
|
@ -199,12 +199,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
|
|||
)
|
||||
};
|
||||
|
||||
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())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -343,7 +341,7 @@ pub struct CodegenContext {
|
|||
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,
|
||||
|
@ -392,7 +390,7 @@ impl CodegenContext {
|
|||
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());
|
||||
}
|
||||
}
|
||||
|
@ -400,13 +398,13 @@ impl CodegenContext {
|
|||
|
||||
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 _);
|
||||
|
@ -495,7 +493,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
|
|||
-> 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")
|
||||
}
|
||||
|
@ -617,192 +615,191 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
-> 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));
|
||||
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: &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 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("write-bc");
|
||||
}
|
||||
|
||||
if config.embed_bitcode {
|
||||
embed_bitcode(cgcx, llcx, llmod, Some(data));
|
||||
timeline.record("embed-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 config.embed_bitcode {
|
||||
embed_bitcode(cgcx, llcx, llmod, Some(data));
|
||||
timeline.record("embed-bc");
|
||||
}
|
||||
timeline.record("compress-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));
|
||||
}
|
||||
timeline.record("compress-bc");
|
||||
}
|
||||
} else if config.embed_bitcode_marker {
|
||||
embed_bitcode(cgcx, llcx, llmod, None);
|
||||
}
|
||||
} 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);
|
||||
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)
|
||||
};
|
||||
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 input = match str::from_utf8(input) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return 0,
|
||||
};
|
||||
let input = match str::from_utf8(input) {
|
||||
Ok(s) => s,
|
||||
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 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,
|
||||
};
|
||||
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 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 !config.emit_asm && !cgcx.save_temps {
|
||||
drop(fs::remove_file(&assembly));
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
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);
|
||||
Ok(module.into_compiled_module(config.emit_obj,
|
||||
config.emit_bc,
|
||||
config.emit_bc_compressed,
|
||||
|
@ -828,8 +825,8 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
/// 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(
|
||||
|
@ -2050,7 +2047,7 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path,
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -2353,7 +2350,7 @@ fn msvc_imps_needed(tcx: TyCtxt) -> 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
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ use super::ModuleKind;
|
|||
|
||||
use abi;
|
||||
use back::link;
|
||||
use back::write::{self, OngoingCodegen, create_target_machine};
|
||||
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
|
||||
use back::write::{self, OngoingCodegen};
|
||||
use llvm::{ValueRef, Vector, get_param};
|
||||
use llvm;
|
||||
use metadata;
|
||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
|
@ -59,7 +59,7 @@ use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
|
|||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||
use common::{self, C_struct_in_context, C_array, val_ty};
|
||||
use consts;
|
||||
use context::{self, CodegenCx};
|
||||
use context::CodegenCx;
|
||||
use debuginfo;
|
||||
use declare;
|
||||
use meth;
|
||||
|
@ -77,7 +77,6 @@ use rustc_data_structures::sync::Lrc;
|
|||
|
||||
use std::any::Any;
|
||||
use std::ffi::CString;
|
||||
use std::str;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Instant, Duration};
|
||||
use std::i32;
|
||||
|
@ -609,16 +608,14 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
|
|||
}
|
||||
|
||||
fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||
llmod_id: &str,
|
||||
llvm_module: &ModuleLlvm,
|
||||
link_meta: &LinkMeta)
|
||||
-> (ContextRef, ModuleRef, EncodedMetadata) {
|
||||
-> EncodedMetadata {
|
||||
use std::io::Write;
|
||||
use flate2::Compression;
|
||||
use flate2::write::DeflateEncoder;
|
||||
|
||||
let (metadata_llcx, metadata_llmod) = unsafe {
|
||||
context::create_context_and_module(tcx.sess, llmod_id)
|
||||
};
|
||||
let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod());
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum MetadataKind {
|
||||
|
@ -641,14 +638,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
}).max().unwrap_or(MetadataKind::None);
|
||||
|
||||
if kind == MetadataKind::None {
|
||||
return (metadata_llcx,
|
||||
metadata_llmod,
|
||||
EncodedMetadata::new());
|
||||
return EncodedMetadata::new();
|
||||
}
|
||||
|
||||
let metadata = tcx.encode_metadata(link_meta);
|
||||
if kind == MetadataKind::Uncompressed {
|
||||
return (metadata_llcx, metadata_llmod, metadata);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
assert!(kind == MetadataKind::Compressed);
|
||||
|
@ -676,7 +671,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
let directive = CString::new(directive).unwrap();
|
||||
llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
|
||||
}
|
||||
return (metadata_llcx, metadata_llmod, metadata);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
pub struct ValueIter {
|
||||
|
@ -698,7 +693,7 @@ impl Iterator for ValueIter {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
|
||||
pub fn iter_globals(llmod: &llvm::Module) -> ValueIter {
|
||||
unsafe {
|
||||
ValueIter {
|
||||
cur: llvm::LLVMGetFirstGlobal(llmod),
|
||||
|
@ -731,19 +726,15 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
// Codegen the metadata.
|
||||
let llmod_id = "metadata";
|
||||
let (metadata_llcx, metadata_llmod, metadata) =
|
||||
time(tcx.sess, "write metadata", || {
|
||||
write_metadata(tcx, llmod_id, &link_meta)
|
||||
});
|
||||
let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id);
|
||||
let metadata = time(tcx.sess, "write metadata", || {
|
||||
write_metadata(tcx, &metadata_llvm_module, &link_meta)
|
||||
});
|
||||
|
||||
let metadata_module = ModuleCodegen {
|
||||
name: link::METADATA_MODULE_NAME.to_string(),
|
||||
llmod_id: llmod_id.to_string(),
|
||||
source: ModuleSource::Codegened(ModuleLlvm {
|
||||
llcx: metadata_llcx,
|
||||
llmod: metadata_llmod,
|
||||
tm: create_target_machine(tcx.sess, false),
|
||||
}),
|
||||
source: ModuleSource::Codegened(metadata_llvm_module),
|
||||
kind: ModuleKind::Metadata,
|
||||
};
|
||||
|
||||
|
@ -803,13 +794,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
|
||||
unsafe {
|
||||
let llmod_id = "allocator";
|
||||
let (llcx, llmod) =
|
||||
context::create_context_and_module(tcx.sess, llmod_id);
|
||||
let modules = ModuleLlvm {
|
||||
llmod,
|
||||
llcx,
|
||||
tm: create_target_machine(tcx.sess, false),
|
||||
};
|
||||
let modules = ModuleLlvm::new(tcx.sess, llmod_id);
|
||||
time(tcx.sess, "write allocator module", || {
|
||||
allocator::codegen(tcx, &modules, kind)
|
||||
});
|
||||
|
@ -1200,8 +1185,9 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
.to_fingerprint().to_hex());
|
||||
|
||||
// Instantiate monomorphizations without filling out definitions yet...
|
||||
let cx = CodegenCx::new(tcx, cgu, &llmod_id);
|
||||
let module = {
|
||||
let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
|
||||
let stats = {
|
||||
let cx = CodegenCx::new(tcx, cgu, &llvm_module);
|
||||
let mono_items = cx.codegen_unit
|
||||
.items_in_deterministic_order(cx.tcx);
|
||||
for &(mono_item, (linkage, visibility)) in &mono_items {
|
||||
|
@ -1248,21 +1234,15 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
debuginfo::finalize(&cx);
|
||||
}
|
||||
|
||||
let llvm_module = ModuleLlvm {
|
||||
llcx: cx.llcx,
|
||||
llmod: cx.llmod,
|
||||
tm: create_target_machine(cx.sess(), false),
|
||||
};
|
||||
|
||||
ModuleCodegen {
|
||||
name: cgu_name,
|
||||
source: ModuleSource::Codegened(llvm_module),
|
||||
kind: ModuleKind::Regular,
|
||||
llmod_id,
|
||||
}
|
||||
cx.stats.into_inner()
|
||||
};
|
||||
|
||||
(cx.into_stats(), module)
|
||||
(stats, ModuleCodegen {
|
||||
name: cgu_name,
|
||||
source: ModuleSource::Codegened(llvm_module),
|
||||
kind: ModuleKind::Regular,
|
||||
llmod_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//! Code that is useful in various codegen modules.
|
||||
|
||||
use llvm;
|
||||
use llvm::{ValueRef, ContextRef, TypeKind};
|
||||
use llvm::{ValueRef, TypeKind};
|
||||
use llvm::{True, False, Bool, OperandBundleDef};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::lang_items::LangItem;
|
||||
|
@ -225,7 +225,7 @@ pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef {
|
|||
C_struct_in_context(cx.llcx, elts, packed)
|
||||
}
|
||||
|
||||
pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
|
||||
pub fn C_struct_in_context(llcx: &llvm::Context, elts: &[ValueRef], packed: bool) -> ValueRef {
|
||||
unsafe {
|
||||
llvm::LLVMConstStructInContext(llcx,
|
||||
elts.as_ptr(), elts.len() as c_uint,
|
||||
|
@ -249,7 +249,7 @@ pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef {
|
|||
C_bytes_in_context(cx.llcx, bytes)
|
||||
}
|
||||
|
||||
pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
|
||||
pub fn C_bytes_in_context(llcx: &llvm::Context, bytes: &[u8]) -> ValueRef {
|
||||
unsafe {
|
||||
let ptr = bytes.as_ptr() as *const c_char;
|
||||
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use common;
|
||||
use llvm;
|
||||
use llvm::{ContextRef, ModuleRef, ValueRef};
|
||||
use llvm::ValueRef;
|
||||
use rustc::dep_graph::DepGraphSafe;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
|
@ -42,16 +42,16 @@ use syntax::symbol::LocalInternedString;
|
|||
use abi::Abi;
|
||||
|
||||
/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
|
||||
/// `ContextRef` so that several compilation units may be optimized in parallel.
|
||||
/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`.
|
||||
/// `llvm::Context` so that several compilation units may be optimized in parallel.
|
||||
/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
|
||||
pub struct CodegenCx<'a, 'tcx: 'a> {
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub check_overflow: bool,
|
||||
pub use_dll_storage_attrs: bool,
|
||||
pub tls_model: llvm::ThreadLocalMode,
|
||||
|
||||
pub llmod: ModuleRef,
|
||||
pub llcx: ContextRef,
|
||||
pub llmod: &'a llvm::Module,
|
||||
pub llcx: &'a llvm::Context,
|
||||
pub stats: RefCell<Stats>,
|
||||
pub codegen_unit: Arc<CodegenUnit<'tcx>>,
|
||||
|
||||
|
@ -94,7 +94,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
|
|||
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
|
||||
pub isize_ty: Type,
|
||||
|
||||
pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
|
||||
pub dbg_cx: Option<debuginfo::CrateDebugContext<'a, 'tcx>>,
|
||||
|
||||
eh_personality: Cell<Option<ValueRef>>,
|
||||
eh_unwind_resume: Cell<Option<ValueRef>>,
|
||||
|
@ -155,8 +155,7 @@ pub fn is_pie_binary(sess: &Session) -> bool {
|
|||
!is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
|
||||
}
|
||||
|
||||
pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
|
||||
let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
|
||||
pub unsafe fn create_module(sess: &Session, llcx: &'ll llvm::Context, mod_name: &str) -> &'ll llvm::Module {
|
||||
let mod_name = CString::new(mod_name).unwrap();
|
||||
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
|
||||
|
||||
|
@ -208,13 +207,13 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont
|
|||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
}
|
||||
|
||||
(llcx, llmod)
|
||||
llmod
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
codegen_unit: Arc<CodegenUnit<'tcx>>,
|
||||
llmod_id: &str)
|
||||
llvm_module: &'a ::ModuleLlvm)
|
||||
-> CodegenCx<'a, 'tcx> {
|
||||
// An interesting part of Windows which MSVC forces our hand on (and
|
||||
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
|
||||
|
@ -265,56 +264,49 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
|||
|
||||
let tls_model = get_tls_model(&tcx.sess);
|
||||
|
||||
unsafe {
|
||||
let (llcx, llmod) = create_context_and_module(&tcx.sess,
|
||||
&llmod_id[..]);
|
||||
let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
|
||||
|
||||
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 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());
|
||||
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),
|
||||
}
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_stats(self) -> Stats {
|
||||
self.stats.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
|
||||
|
|
|
@ -862,7 +862,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt,
|
|||
return unit_metadata;
|
||||
};
|
||||
|
||||
fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef {
|
||||
fn path_to_mdstring(llcx: &llvm::Context, path: &Path) -> llvm::ValueRef {
|
||||
let path_str = path2cstr(path);
|
||||
unsafe {
|
||||
llvm::LLVMMDStringInContext(llcx,
|
||||
|
|
|
@ -21,7 +21,7 @@ use self::metadata::{type_metadata, file_metadata, TypeMap};
|
|||
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
|
||||
|
||||
use llvm;
|
||||
use llvm::{ModuleRef, ContextRef, ValueRef};
|
||||
use llvm::ValueRef;
|
||||
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
|
||||
use rustc::hir::CodegenFnAttrFlags;
|
||||
use rustc::hir::def_id::{DefId, CrateNum};
|
||||
|
@ -67,9 +67,9 @@ const DW_TAG_auto_variable: c_uint = 0x100;
|
|||
const DW_TAG_arg_variable: c_uint = 0x101;
|
||||
|
||||
/// A context object for maintaining all state needed by the debuginfo module.
|
||||
pub struct CrateDebugContext<'tcx> {
|
||||
llcontext: ContextRef,
|
||||
llmod: ModuleRef,
|
||||
pub struct CrateDebugContext<'a, 'tcx> {
|
||||
llcontext: &'a llvm::Context,
|
||||
llmod: &'a llvm::Module,
|
||||
builder: DIBuilderRef,
|
||||
created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>,
|
||||
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), DIType>>,
|
||||
|
@ -82,8 +82,8 @@ pub struct CrateDebugContext<'tcx> {
|
|||
composite_types_completed: RefCell<FxHashSet<DIType>>,
|
||||
}
|
||||
|
||||
impl<'tcx> CrateDebugContext<'tcx> {
|
||||
pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
|
||||
impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
|
||||
pub fn new(llmod: &'a llvm::Module) -> Self {
|
||||
debug!("CrateDebugContext::new");
|
||||
let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
|
||||
// DIBuilder inherits context from the module, so we'd better use the same one
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc {
|
|||
|
||||
#[inline]
|
||||
pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>)
|
||||
-> &'a CrateDebugContext<'tcx> {
|
||||
-> &'a CrateDebugContext<'a, 'tcx> {
|
||||
cx.dbg_cx.as_ref().unwrap()
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(fs_read_write)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![allow(unused_attributes)]
|
||||
#![feature(libc)]
|
||||
#![feature(quote)]
|
||||
|
@ -34,6 +36,7 @@
|
|||
#![feature(link_args)]
|
||||
#![feature(static_nobundle)]
|
||||
|
||||
use back::write::create_target_machine;
|
||||
use rustc::dep_graph::WorkProduct;
|
||||
use syntax_pos::symbol::Symbol;
|
||||
|
||||
|
@ -340,22 +343,41 @@ enum ModuleSource {
|
|||
Codegened(ModuleLlvm),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ModuleLlvm {
|
||||
llcx: llvm::ContextRef,
|
||||
llmod: llvm::ModuleRef,
|
||||
tm: llvm::TargetMachineRef,
|
||||
llcx: &'static mut llvm::Context,
|
||||
llmod_raw: *const llvm::Module,
|
||||
tm: &'static mut llvm::TargetMachine,
|
||||
}
|
||||
|
||||
unsafe impl Send for ModuleLlvm { }
|
||||
unsafe impl Sync for ModuleLlvm { }
|
||||
|
||||
impl ModuleLlvm {
|
||||
fn new(sess: &Session, mod_name: &str) -> Self {
|
||||
unsafe {
|
||||
let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
|
||||
let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _;
|
||||
|
||||
ModuleLlvm {
|
||||
llmod_raw,
|
||||
llcx,
|
||||
tm: create_target_machine(sess, false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn llmod(&self) -> &llvm::Module {
|
||||
unsafe {
|
||||
&*self.llmod_raw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ModuleLlvm {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
llvm::LLVMDisposeModule(self.llmod);
|
||||
llvm::LLVMContextDispose(self.llcx);
|
||||
llvm::LLVMRustDisposeTargetMachine(self.tm);
|
||||
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
|
||||
llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -375,10 +375,8 @@ pub enum ThreadLocalMode {
|
|||
}
|
||||
|
||||
// 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; }
|
||||
|
@ -407,8 +405,8 @@ extern { pub type SectionIterator_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; }
|
||||
|
@ -498,43 +496,42 @@ extern { pub type ModuleBuffer; }
|
|||
#[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,
|
||||
|
@ -547,7 +544,7 @@ extern "C" {
|
|||
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)
|
||||
|
@ -563,9 +560,9 @@ extern "C" {
|
|||
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;
|
||||
|
@ -589,9 +586,9 @@ extern "C" {
|
|||
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;
|
||||
|
@ -604,12 +601,12 @@ extern "C" {
|
|||
|
||||
|
||||
// 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)
|
||||
|
@ -679,7 +676,6 @@ extern "C" {
|
|||
|
||||
|
||||
// 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);
|
||||
|
@ -694,10 +690,10 @@ extern "C" {
|
|||
|
||||
// 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;
|
||||
|
@ -706,15 +702,15 @@ extern "C" {
|
|||
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;
|
||||
|
@ -736,7 +732,7 @@ extern "C" {
|
|||
// 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;
|
||||
|
@ -767,7 +763,7 @@ extern "C" {
|
|||
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);
|
||||
|
@ -1277,7 +1273,7 @@ extern "C" {
|
|||
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;
|
||||
|
@ -1289,13 +1285,13 @@ extern "C" {
|
|||
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();
|
||||
|
||||
|
@ -1351,7 +1347,7 @@ extern "C" {
|
|||
/// 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,
|
||||
|
@ -1371,11 +1367,11 @@ extern "C" {
|
|||
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);
|
||||
|
||||
|
@ -1582,7 +1578,7 @@ extern "C" {
|
|||
TypeArray: DIArray);
|
||||
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
|
||||
pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &Context,
|
||||
Line: c_uint,
|
||||
Column: c_uint,
|
||||
Scope: DIScope,
|
||||
|
@ -1618,11 +1614,11 @@ extern "C" {
|
|||
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,
|
||||
|
@ -1633,17 +1629,17 @@ extern "C" {
|
|||
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,
|
||||
|
@ -1651,10 +1647,10 @@ extern "C" {
|
|||
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;
|
||||
|
@ -1669,7 +1665,7 @@ extern "C" {
|
|||
|
||||
pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef);
|
||||
|
||||
pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
|
||||
pub fn LLVMContextSetDiagnosticHandler(C: &Context,
|
||||
Handler: DiagnosticHandler,
|
||||
DiagnosticContext: *mut c_void);
|
||||
|
||||
|
@ -1688,7 +1684,7 @@ extern "C" {
|
|||
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);
|
||||
|
||||
|
@ -1706,7 +1702,7 @@ extern "C" {
|
|||
-> 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,
|
||||
|
@ -1716,21 +1712,21 @@ extern "C" {
|
|||
|
||||
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;
|
||||
|
@ -1742,34 +1738,34 @@ extern "C" {
|
|||
) -> *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;
|
||||
|
|
|
@ -127,7 +127,7 @@ pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
|
|||
// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
|
||||
// function.
|
||||
// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
|
||||
pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
|
||||
pub fn SetUniqueComdat(llmod: &Module, val: ValueRef) {
|
||||
unsafe {
|
||||
LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use llvm;
|
||||
use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind};
|
||||
use llvm::{TypeRef, Bool, False, True, TypeKind};
|
||||
use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
|
||||
|
||||
use context::CodegenCx;
|
||||
|
@ -77,7 +77,7 @@ impl Type {
|
|||
ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
|
||||
}
|
||||
|
||||
pub fn i8_llcx(llcx: ContextRef) -> Type {
|
||||
pub fn i8_llcx(llcx: &llvm::Context) -> Type {
|
||||
ty!(llvm::LLVMInt8TypeInContext(llcx))
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ impl Type {
|
|||
}
|
||||
|
||||
// Creates an integer type with the given number of bits, e.g. i24
|
||||
pub fn ix_llcx(llcx: ContextRef, num_bits: u64) -> Type {
|
||||
pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> Type {
|
||||
ty!(llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint))
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ impl Type {
|
|||
Type::i8(cx).ptr_to()
|
||||
}
|
||||
|
||||
pub fn i8p_llcx(llcx: ContextRef) -> Type {
|
||||
pub fn i8p_llcx(llcx: &llvm::Context) -> Type {
|
||||
Type::i8_llcx(llcx).ptr_to()
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue