Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,14 @@ fn write_output_file<'ll>(
std::ptr::null()
};
let result = unsafe {
let pm = llvm::LLVMCreatePassManager();
llvm::LLVMAddAnalysisPasses(target, pm);
llvm::LLVMRustAddLibraryInfo(target, pm, m, no_builtins);
llvm::LLVMRustWriteOutputFile(
target,
pm,
m,
output_c.as_ptr(),
dwo_output_ptr,
file_type,
verify_llvm_ir,
no_builtins,
)
};

Expand Down
15 changes: 1 addition & 14 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,6 @@ unsafe extern "C" {
}
#[repr(C)]
pub(crate) struct Builder<'a>(InvariantOpaque<'a>);
#[repr(C)]
pub(crate) struct PassManager<'a>(InvariantOpaque<'a>);
unsafe extern "C" {
pub type TargetMachine;
}
Expand Down Expand Up @@ -1637,11 +1635,6 @@ unsafe extern "C" {
/// Writes a module to the specified path. Returns 0 on success.
pub(crate) fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;

/// Creates a legacy pass manager -- only used for final codegen.
pub(crate) fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;

pub(crate) fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>);

pub(crate) fn LLVMGetHostCPUFeatures() -> *mut c_char;

pub(crate) fn LLVMDisposeMessage(message: *mut c_char);
Expand Down Expand Up @@ -2430,20 +2423,14 @@ unsafe extern "C" {

pub(crate) fn LLVMRustDisposeMCSubtargetInfo(MCInfo: ptr::NonNull<MCSubtargetInfo>);

pub(crate) fn LLVMRustAddLibraryInfo<'a>(
T: &TargetMachine,
PM: &PassManager<'a>,
M: &'a Module,
DisableSimplifyLibCalls: bool,
);
pub(crate) fn LLVMRustWriteOutputFile<'a>(
T: &'a TargetMachine,
PM: *mut PassManager<'a>,
M: &'a Module,
Output: *const c_char,
DwoOutput: *const c_char,
FileType: FileType,
VerifyIR: bool,
DisableSimplifyLibCalls: bool,
) -> LLVMRustResult;
pub(crate) fn LLVMRustOptimize<'a>(
M: &'a Module,
Expand Down
65 changes: 33 additions & 32 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,30 +447,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
return wrap(TM);
}

// Unfortunately, the LLVM C API doesn't provide a way to create the
// TargetLibraryInfo pass, so we use this method to do so.
extern "C" void LLVMRustAddLibraryInfo(LLVMTargetMachineRef T,
LLVMPassManagerRef PMR, LLVMModuleRef M,
bool DisableSimplifyLibCalls) {
auto TargetTriple = Triple(unwrap(M)->getTargetTriple());
TargetOptions *Options = &unwrap(T)->Options;
auto TLII = TargetLibraryInfoImpl(TargetTriple);
if (DisableSimplifyLibCalls)
TLII.disableAllFunctions();
unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
#if LLVM_VERSION_GE(24, 0)
// LLVM 24 removed TargetOptions::EABIVersion and ExceptionModel; the EABI
// version and exception model are now derived from the target triple and
// module flags respectively instead.
unwrap(PMR)->add(new RuntimeLibraryInfoWrapper(Options->MCOptions.ABIName,
Options->VecLib));
#elif LLVM_VERSION_GE(22, 0)
unwrap(PMR)->add(new RuntimeLibraryInfoWrapper(
TargetTriple, Options->ExceptionModel, Options->FloatABIType,
Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib));
#endif
}

extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
// Initializing the command-line options more than once is not allowed. So,
// check if they've already been initialized. (This could happen if we're
Expand Down Expand Up @@ -500,10 +476,34 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) {
}

extern "C" LLVMRustResult
LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
LLVMModuleRef M, const char *Path, const char *DwoPath,
LLVMRustFileType RustFileType, bool VerifyIR) {
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M,
const char *Path, const char *DwoPath,
LLVMRustFileType RustFileType, bool VerifyIR,
bool DisableSimplifyLibCalls) {
std::unique_ptr<llvm::legacy::PassManager> PM =
std::make_unique<llvm::legacy::PassManager>();

PM->add(createTargetTransformInfoWrapperPass(
unwrap(Target)->getTargetIRAnalysis()));

auto TargetTriple = Triple(unwrap(M)->getTargetTriple());
TargetOptions *Options = &unwrap(Target)->Options;
auto TLII = TargetLibraryInfoImpl(TargetTriple);
if (DisableSimplifyLibCalls)
TLII.disableAllFunctions();
PM->add(new TargetLibraryInfoWrapperPass(TLII));
#if LLVM_VERSION_GE(24, 0)
// LLVM 24 removed TargetOptions::EABIVersion and ExceptionModel; the EABI
// version and exception model are now derived from the target triple and
// module flags respectively instead.
PM->add(new RuntimeLibraryInfoWrapper(Options->MCOptions.ABIName,
Options->VecLib));
#elif LLVM_VERSION_GE(22, 0)
PM->add(new RuntimeLibraryInfoWrapper(
TargetTriple, Options->ExceptionModel, Options->FloatABIType,
Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib));
#endif

auto FileType = fromRust(RustFileType);

std::string ErrorInfo;
Expand All @@ -516,6 +516,9 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
return LLVMRustResult::Failure;
}

// TargetMachine::addPassesToEmitFile stores pointers to the output streams
// in a couple of places inside of the object. Explicitly delete the PM after
// we call run() to avoid dangling references.
auto BOS = buffer_ostream(OS);
if (DwoPath) {
auto DOS = raw_fd_ostream(DwoPath, EC, sys::fs::OF_None);
Expand All @@ -529,15 +532,13 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
auto DBOS = buffer_ostream(DOS);
unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, !VerifyIR);
PM->run(*unwrap(M));
PM.reset();
} else {
unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, !VerifyIR);
PM->run(*unwrap(M));
PM.reset();
}

// Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
// stream (OS), so the only real safe place to delete this is here? Don't we
// wish this was written in Rust?
LLVMDisposePassManager(PMR);
Comment thread
boomanaiden154 marked this conversation as resolved.
return LLVMRustResult::Success;
}

Expand Down
Loading