Skip to content
7 changes: 5 additions & 2 deletions quadrants/codegen/llvm/codegen_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2435,7 +2435,9 @@ LLVMCompiledTask TaskCodeGenLLVM::run_compilation() {
if (get_environ_config(DUMP_IR_ENV.data())) {
std::filesystem::create_directories(ir_dump_dir);

std::filesystem::path filename = ir_dump_dir / (kernel->name + "_llvm.ll");
QD_ASSERT(!offloaded_tasks.empty());
std::string dump_name = offloaded_tasks[0].name;
std::filesystem::path filename = ir_dump_dir / (dump_name + "_llvm.ll");
Comment on lines +2439 to +2440
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Sanitize task name before constructing LLVM dump filename

Using offloaded_tasks[0].name directly in the path makes dump/load filenames inherit raw loop names from qd.loop_config(name=...) (via init_offloaded_task_function), and those names are not constrained to filesystem-safe characters. When a loop name includes separators or reserved characters (for example /, \, :, ?), QD_DUMP_IR/QD_LOAD_IR can fail to open the file or resolve outside the intended dump directory.

Useful? React with 👍 / 👎.

std::error_code EC;
llvm::raw_fd_ostream dest_file(filename.string(), EC);
if (!EC) {
Expand All @@ -2444,7 +2446,8 @@ LLVMCompiledTask TaskCodeGenLLVM::run_compilation() {
}

if (get_environ_config(LOAD_IR_ENV.data())) {
std::filesystem::path filename = ir_dump_dir / (kernel->name + "_llvm.ll");
QD_ASSERT(!offloaded_tasks.empty());
std::filesystem::path filename = ir_dump_dir / (offloaded_tasks[0].name + "_llvm.ll");
llvm::SMDiagnostic err;
auto loaded_module = llvm::parseAssemblyFile(filename.string(), err, *llvm_context);
if (!loaded_module) {
Comment thread
claude[bot] marked this conversation as resolved.
Expand Down
26 changes: 15 additions & 11 deletions quadrants/runtime/cuda/jit_cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,18 @@ JITSessionCUDA::JITSessionCUDA(QuadrantsLLVMContext *tlctx,

JITModule *JITSessionCUDA::add_module(std::unique_ptr<llvm::Module> M, int max_reg) {
const char *dump_ir_env = std::getenv(DUMP_IR_ENV.data());
if (dump_ir_env != nullptr && std::string(dump_ir_env) == "1") {
const char *load_ptx_env = std::getenv("QUADRANTS_LOAD_PTX");

// Capture the dump name before compile_module_to_ptx renames functions via convert().
std::string dump_name;
if (dump_ir_env != nullptr || load_ptx_env != nullptr) {
dump_name = moduleToDumpName(M.get());
Comment on lines +89 to +92
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize PTX dump names before using them as file paths

Capturing dump_name before compile_module_to_ptx() means the .ptx dump/load path now uses raw symbol names instead of the post-convert() names. In cases where task names contain filesystem-reserved characters (or Windows-mangled symbols include them), QUADRANTS_LOAD_PTX may look for a different/invalid path and fail to load the intended PTX file.

Useful? React with 👍 / 👎.

}

if (dump_ir_env != nullptr && std::string(dump_ir_env) == "1" && !dump_name.empty()) {
std::filesystem::path ir_dump_dir = config_.debug_dump_path;
std::filesystem::create_directories(ir_dump_dir);
std::string dumpName = moduleToDumpName(M.get());
std::filesystem::path filename = ir_dump_dir / (dumpName + "_before_ptx.ll");
std::filesystem::path filename = ir_dump_dir / (dump_name + "_before_ptx.ll");
std::error_code EC;
llvm::raw_fd_ostream dest_file(filename.string(), EC);
if (!EC) {
Expand All @@ -105,22 +112,19 @@ JITModule *JITSessionCUDA::add_module(std::unique_ptr<llvm::Module> M, int max_r
writer.write(ptx);
}

if (dump_ir_env != nullptr) {
if (dump_ir_env != nullptr && !dump_name.empty()) {
std::filesystem::path ir_dump_dir = config_.debug_dump_path;
std::filesystem::create_directories(ir_dump_dir);
std::string dumpName = moduleToDumpName(M.get());
std::filesystem::path ptx_path = ir_dump_dir / (dumpName + ".ptx");
std::filesystem::path ptx_path = ir_dump_dir / (dump_name + ".ptx");
if (std::ofstream out_file(ptx_path); out_file.is_open()) {
out_file << ptx << std::endl;
std::cout << "PTX dumped to: " << ptx_path.string() << std::endl;
}
std::cout << "PTX dumped to: " << ptx_path.string() << std::endl;
}

const char *load_ptx_env = std::getenv("QUADRANTS_LOAD_PTX");
if (load_ptx_env != nullptr) {
if (load_ptx_env != nullptr && !dump_name.empty()) {
std::filesystem::path ir_dump_dir = config_.debug_dump_path;
std::string dumpName = moduleToDumpName(M.get());
std::filesystem::path ptx_path = ir_dump_dir / (dumpName + ".ptx");
std::filesystem::path ptx_path = ir_dump_dir / (dump_name + ".ptx");
std::ifstream in_file(ptx_path);
if (in_file.is_open()) {
QD_INFO("Loading PTX from file: {}", ptx_path.string());
Expand Down
Loading