* This program is free software, you can redistribute it and/or modify.
* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* This file is a part of the CANN Open Software.
* Licensed under CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. See LICENSE in the root of
* the software repository for the full text of the License.
*/
#include "jit_util.h"
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <stdexcept>
#include <sys/wait.h>
#include <tiling/platform/platform_ascendc.h>
#include "jit_config.h"
#ifndef ENABLE_ASCEND950
#define ENABLE_ASCEND950
#endif
namespace fs = std::filesystem;
namespace CatlassKernel {
namespace {
* @brief Read a non-empty environment variable or return an empty C string.
*/
const char* EnvOrEmpty(const char* name)
{
const char* v = std::getenv(name);
return (v && *v) ? v : "";
}
}
namespace {
std::string shellQuote(const std::string& arg)
{
std::string result = "'";
for (char c : arg) {
if (c == '\'') {
result += "'\\''";
} else {
result += c;
}
}
result += "'";
return result;
}
}
ProcessResult RunProcessCapture(const std::vector<std::string>& args)
{
JIT_THROW_IF(args.empty() || args[0].empty(), "empty compiler command");
std::string cmd;
for (size_t i = 0; i < args.size(); ++i) {
if (i > 0)
cmd += ' ';
cmd += shellQuote(args[i]);
}
cmd += " 2>&1";
FILE* fp = ::popen(cmd.c_str(), "r");
JIT_THROW_IF(!fp, std::string("popen failed: ") + std::strerror(errno));
std::string output;
char buf[4096];
while (std::fgets(buf, sizeof(buf), fp) != nullptr) {
output += buf;
}
const int status = ::pclose(fp);
ProcessResult result;
result.output = std::move(output);
if (WIFEXITED(status)) {
result.exitCode = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
result.exitCode = 128 + WTERMSIG(status);
} else {
result.exitCode = -1;
}
return result;
}
std::string GetCurrentNPUArch()
{
const platform_ascendc::SocVersion socVersion =
platform_ascendc::PlatformAscendCManager::GetInstance()->GetSocVersion();
switch (socVersion) {
case platform_ascendc::SocVersion::ASCEND910B:
case platform_ascendc::SocVersion::ASCEND910_93:
return "2201";
#if defined(ENABLE_ASCEND950)
case platform_ascendc::SocVersion::ASCEND950:
return "3510";
#endif
default:
JIT_THROW("unsupported Ascend SocVersion: " + std::to_string(static_cast<int>(socVersion)));
}
}
std::string FindCompilerPath()
{
std::error_code ec;
const char* ascendHome = EnvOrEmpty(JitConfig::kAscendHomeEnv);
if (*ascendHome) {
for (const char* suffix : JitConfig::kCcecSuffixes) {
const std::string path = std::string(ascendHome) + suffix;
if (fs::is_regular_file(path, ec)) {
return path;
}
}
}
return "ccec";
}
std::vector<std::string> BuildIncludeArgsFromEnv()
{
std::vector<std::string> args;
const char* pkgDir = EnvOrEmpty(JitConfig::kPkgDirEnv);
if (*pkgDir) {
args.push_back("-I" + std::string(pkgDir) + "/include");
args.push_back("-I" + std::string(pkgDir) + "/jit");
}
return args;
}
std::string ResolveTemplateBase()
{
const char* pkgDir = EnvOrEmpty(JitConfig::kPkgDirEnv);
if (*pkgDir) {
return std::string(pkgDir) + "/jit/templates/";
}
return {};
}
}