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
51 changes: 51 additions & 0 deletions clang/lib/DPCT/CommandOption/ValidateArguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,63 @@

using namespace llvm;
using namespace std;
using namespace clang::tooling;
namespace path = llvm::sys::path;
namespace fs = llvm::sys::fs;


extern UnifiedPath CudaPath;
extern UnifiedPath DpctInstallPath;

namespace clang {
namespace dpct {

// To validate the root path of the project to be migrated.
void validateInputDirectory(UnifiedPath InRootPath) {
if (isChildOrSamePath(CudaPath, InRootPath)) {
ShowStatus(MigrationErrorRunFromSDKFolder);
dpctExit(MigrationErrorRunFromSDKFolder);
}
if (isChildOrSamePath(InRootPath, CudaPath)) {
ShowStatus(MigrationErrorInputDirContainSDKFolder);
dpctExit(MigrationErrorInputDirContainSDKFolder);
}

if (isChildOrSamePath(InRootPath, DpctInstallPath)) {
ShowStatus(MigrationErrorInputDirContainCTTool);
dpctExit(MigrationErrorInputDirContainCTTool);
}
}

void validateInputDirectoryLengthOrExit(string OptionName, UnifiedPath Path){
if (Path.getPath().size() >= MAX_PATH_LEN - 1) {
DpctLog() << "Error: " << OptionName << " '" << Path.getPath() << "' is too long\n";
ShowStatus(MigrationErrorPathTooLong);
dpctExit(MigrationErrorPathTooLong);
}
}
void checkOptionLengthLimitOrExit(string OptionName, string OptionValue, int Limit)
{
if (OptionValue.size() >= Limit) {
DpctLog() << "Error: " << OptionName << " '" << OptionValue
<< "' is too long\n";
ShowStatus(MigrationErrorPrefixTooLong);
dpctExit(MigrationErrorPrefixTooLong);
}
}

void checkSpecialCharsOrExit(string OptionName, string OptionValue) {
auto P = std::find_if_not(
OptionValue.begin(), OptionValue.end(),
[](char C) { return ::isalpha(C) || ::isdigit(C) || C == '_'; });
if (P != OptionValue.end()) {
DpctLog() << "Error: " << OptionName << " contains special character '"
<< *P << "' \n";
ShowStatus(MigrationErrorSpecialCharacter);
dpctExit(MigrationErrorSpecialCharacter);
}
}

bool isOutRootAccess(SmallString<256> &OutRoot) {
if (!fs::can_write(OutRoot)) {
llvm::errs() << "Could not access out-root directory.\n";
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/DPCT/CommandOption/ValidateArguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ bool checkReportArgs(ReportTypeEnum &RType, ReportFormatEnum &RFormat,
/// -1: Path is invalid
int checkSDKPathOrIncludePath(clang::tooling::UnifiedPath &Path);

void validateInputDirectory(clang::tooling::UnifiedPath InRootPath);
void validateInputDirectoryLengthOrExit(std::string OptionName, clang::tooling::UnifiedPath Path);
void checkOptionLengthLimitOrExit(std::string OptionName, std::string OptionValue, int Limit=128);
void checkSpecialCharsOrExit(std::string OptionName, std::string OptionValue);
} // namespace dpct
} // namespace clang
#endif // DPCT_VALIDATE_ARGUMENTS_H
241 changes: 103 additions & 138 deletions clang/lib/DPCT/DPCT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
Expand Down Expand Up @@ -229,22 +230,7 @@ UnifiedPath getInstallPath(const char *invokeCommand) {
return InstalledPath;
}

// To validate the root path of the project to be migrated.
void ValidateInputDirectory(UnifiedPath InRootPath) {
if (isChildOrSamePath(CudaPath, InRootPath)) {
ShowStatus(MigrationErrorRunFromSDKFolder);
dpctExit(MigrationErrorRunFromSDKFolder);
}
if (isChildOrSamePath(InRootPath, CudaPath)) {
ShowStatus(MigrationErrorInputDirContainSDKFolder);
dpctExit(MigrationErrorInputDirContainSDKFolder);
}

if (isChildOrSamePath(InRootPath, DpctInstallPath)) {
ShowStatus(MigrationErrorInputDirContainCTTool);
dpctExit(MigrationErrorInputDirContainCTTool);
}
}

unsigned int GetLinesNumber(clang::tooling::RefactoringTool &Tool,
UnifiedPath Path) {
Expand Down Expand Up @@ -500,6 +486,84 @@ static void loadMainSrcFileInfo(clang::tooling::UnifiedPath OutRoot) {
}
}

void processPathToHelperFunction(const char **argv){
auto FindHelperPath = [&](const char *Cmd) {
SmallString<512> Path;
Path = getInstallPath(Cmd).getCanonicalPath();
llvm::sys::path::append(Path, "include");
if (!llvm::sys::fs::exists(Path))
return false;
else if (UseSYCLCompat) {
auto CompatPath = Path;
llvm::sys::path::append(CompatPath, "syclcompat");
if (!llvm::sys::fs::exists(CompatPath))
return false;
}
DpctLog() << Path << '\n';
return true;
};
auto Ret = MigrationSucceeded;
if (UseSYCLCompat) {
auto Success = FindHelperPath("clang");
Success |= FindHelperPath("icpx");
if (!Success) {
DpctLog() << "SYCLcompat is usually installed in include folder of "
"SYCL compiler.\n";
Ret = MigrationErrorInvalidInstallPath;
}
} else if (!FindHelperPath(argv[0])) {
Ret = MigrationErrorInvalidInstallPath;
}
ShowStatus(Ret, "Helper functions");
dpctExit(Ret);
}

void callIndependentToolAndExit(const std::string IndependentTool, int argc, const char **argv) {
SmallString<512> ExecutableScriptPath(DpctInstallPath.getCanonicalPath());
llvm::sys::path::append(ExecutableScriptPath, "bin", IndependentTool);
if (!llvm::sys::fs::exists(ExecutableScriptPath)) {
ShowStatus(MigrationErrorInvalidInstallPath, IndependentTool + " tool");
dpctExit(MigrationErrorInvalidInstallPath);
}
std::string Python = GetPython();
if (Python.empty()) {
ShowStatus(CallIndependentToolError, "python");
dpctExit(CallIndependentToolError);
}
std::string SystemCallCommand =
Python + " " + std::string(ExecutableScriptPath.str());
for (int Index = 2; Index < argc; Index++) {
SystemCallCommand.append(" ");
SystemCallCommand.append(std::string(argv[Index]));
}
int ProcessExitCode = system(SystemCallCommand.c_str());
if (ProcessExitCode) {
ShowStatus(CallIndependentToolError, IndependentTool);
dpctExit(CallIndependentToolError);
}
dpctExit(CallIndependentToolSucceeded);
}

void showReportHeader() {
std::string buf;
llvm::raw_string_ostream OS(buf);
OS << "Generate report: "
<< "report-type:"
<< (ReportType.getValue() == ReportTypeEnum::RTE_All
? "all"
: (ReportType.getValue() == ReportTypeEnum::RTE_APIs
? "apis"
: (ReportType.getValue() == ReportTypeEnum::RTE_Stats
? "stats"
: "diags")))
<< ", report-format:"
<< (ReportFormat.getValue() == ReportFormatEnum::RFE_CSV ? "csv"
: "formatted")
<< ", report-file-prefix:" << ReportFilePrefix << "\n";

PrintMsg(OS.str());
}

int runDPCT(int argc, const char **argv) {

if (argc < 2) {
Expand Down Expand Up @@ -577,126 +641,44 @@ int runDPCT(int argc, const char **argv) {
[](const std::string &Str) { return clang::tooling::UnifiedPath(Str); });
AnalysisScope = AnalysisScopeOpt;

// Action
if (PathToHelperFunction) {
auto FindHelperPath = [&](const char *Cmd) {
SmallString<512> Path;
Path = getInstallPath(Cmd).getCanonicalPath();
llvm::sys::path::append(Path, "include");
if (!llvm::sys::fs::exists(Path))
return false;
else if (UseSYCLCompat) {
auto CompatPath = Path;
llvm::sys::path::append(CompatPath, "syclcompat");
if (!llvm::sys::fs::exists(CompatPath))
return false;
}
DpctLog() << Path << '\n';
return true;
};
auto Ret = MigrationSucceeded;
if (UseSYCLCompat) {
auto Success = FindHelperPath("clang");
Success |= FindHelperPath("icpx");
if (!Success) {
DpctLog() << "SYCLcompat is usually installed in include folder of "
"SYCL compiler.\n";
Ret = MigrationErrorInvalidInstallPath;
}
} else if (!FindHelperPath(argv[0])) {
Ret = MigrationErrorInvalidInstallPath;
}
ShowStatus(Ret, "Helper functions");
dpctExit(Ret);
processPathToHelperFunction(argv);
llvm_unreachable("");
}

if (!OutputFile.empty()) {
// Set handle for libclangTooling to redirect warning message to DpctTerm
clang::tooling::SetDiagnosticOutput(DpctTerm());
}
initWarningIDs();
auto CallIndependentTool = [&](const std::string IndependentTool) {
SmallString<512> ExecutableScriptPath(DpctInstallPath.getCanonicalPath());
llvm::sys::path::append(ExecutableScriptPath, "bin", IndependentTool);
if (!llvm::sys::fs::exists(ExecutableScriptPath)) {
ShowStatus(MigrationErrorInvalidInstallPath, IndependentTool + " tool");
dpctExit(MigrationErrorInvalidInstallPath);
}
std::string Python = GetPython();
if (Python.empty()) {
ShowStatus(CallIndependentToolError, "python");
dpctExit(CallIndependentToolError);
}
std::string SystemCallCommand =
Python + " " + std::string(ExecutableScriptPath.str());
for (int Index = 2; Index < argc; Index++) {
SystemCallCommand.append(" ");
SystemCallCommand.append(std::string(argv[Index]));
}
int ProcessExitCode = system(SystemCallCommand.c_str());
if (ProcessExitCode) {
ShowStatus(CallIndependentToolError, IndependentTool);
dpctExit(CallIndependentToolError);
}
dpctExit(CallIndependentToolSucceeded);
};

#ifndef _WIN32
// Action
if (InterceptBuildCommand)
CallIndependentTool("intercept-build");
callIndependentToolAndExit("intercept-build", argc, argv);
#endif
// Action
if (CodePinReport)
CallIndependentTool("codepin-report.py");
callIndependentToolAndExit("codepin-report.py", argc, argv);

if (AnalysisMode)
DpctGlobalInfo::enableAnalysisMode();

if (InRootPath.getPath().size() >= MAX_PATH_LEN - 1) {
DpctLog() << "Error: --in-root '" << InRootPath.getPath() << "' is too long\n";
ShowStatus(MigrationErrorPathTooLong);
dpctExit(MigrationErrorPathTooLong);
}
if (OutRootPath.getPath().size() >= MAX_PATH_LEN - 1) {
DpctLog() << "Error: --out-root '" << OutRootPath.getPath()
<< "' is too long\n";
ShowStatus(MigrationErrorPathTooLong);
dpctExit(MigrationErrorPathTooLong);
}
if (AnalysisScope.getPath().size() >= MAX_PATH_LEN - 1) {
DpctLog() << "Error: --analysis-scope-path '" << AnalysisScope.getPath()
<< "' is too long\n";
ShowStatus(MigrationErrorPathTooLong);
dpctExit(MigrationErrorPathTooLong);
}
if (CudaIncludePath.getPath().size() >= MAX_PATH_LEN - 1) {
DpctLog() << "Error: --cuda-include-path '" << CudaIncludePath.getPath()
<< "' is too long\n";
ShowStatus(MigrationErrorPathTooLong);
dpctExit(MigrationErrorPathTooLong);
}
if (OutputFile.size() >= MAX_PATH_LEN - 1) {
DpctLog() << "Error: --output-file '" << OutputFile
<< "' is too long\n";
ShowStatus(MigrationErrorPathTooLong);
dpctExit(MigrationErrorPathTooLong);
}
validateInputDirectoryLengthOrExit("--in-root", InRootPath);
validateInputDirectoryLengthOrExit("--out-root", OutRootPath);
validateInputDirectoryLengthOrExit("--analysis-scope-path", AnalysisScope);
validateInputDirectoryLengthOrExit("--cuda-include-path", CudaIncludePath);
validateInputDirectoryLengthOrExit("--output-file", OutputFile);

// Report file prefix is limited to 128, so that <report-type> and
// <report-format> can be extended later
if (ReportFilePrefix.size() >= 128) {
DpctLog() << "Error: --report-file-prefix '" << ReportFilePrefix
<< "' is too long\n";
ShowStatus(MigrationErrorPrefixTooLong);
dpctExit(MigrationErrorPrefixTooLong);
}
auto P = std::find_if_not(
ReportFilePrefix.begin(), ReportFilePrefix.end(),
[](char C) { return ::isalpha(C) || ::isdigit(C) || C == '_'; });
if (P != ReportFilePrefix.end()) {
DpctLog() << "Error: --report-file-prefix contains special character '"
<< *P << "' \n";
ShowStatus(MigrationErrorSpecialCharacter);
dpctExit(MigrationErrorSpecialCharacter);
}
checkOptionLengthLimitOrExit("--report-file-prefix", ReportFilePrefix);
checkSpecialCharsOrExit("--report-file-prefix", ReportFilePrefix);

clock_t StartTime = clock();
// just show -- --help information and then exit

// Action: just show -- --help information and then exit
if (CommonOptionsParser::hasHelpOption(OriginalArgc, argv))
dpctExit(MigrationSucceeded);

Expand Down Expand Up @@ -795,26 +777,9 @@ int runDPCT(int argc, const char **argv) {
dpctExit(MigrationErrorInvalidReportArgs);
}

if (GenReport) {
std::string buf;
llvm::raw_string_ostream OS(buf);
OS << "Generate report: "
<< "report-type:"
<< (ReportType.getValue() == ReportTypeEnum::RTE_All
? "all"
: (ReportType.getValue() == ReportTypeEnum::RTE_APIs
? "apis"
: (ReportType.getValue() == ReportTypeEnum::RTE_Stats
? "stats"
: "diags")))
<< ", report-format:"
<< (ReportFormat.getValue() == ReportFormatEnum::RFE_CSV ? "csv"
: "formatted")
<< ", report-file-prefix:" << ReportFilePrefix << "\n";

PrintMsg(OS.str());
}

if (GenReport)
showReportHeader();

ExtraIncPaths = OptParser->getExtraIncPathList();

if (isCUDAHeaderRequired()) {
Expand Down Expand Up @@ -972,7 +937,7 @@ int runDPCT(int argc, const char **argv) {
Tool.setCompilationDatabaseDir(CompilationsDir.getCanonicalPath().str());

if (isCUDAHeaderRequired())
ValidateInputDirectory(InRootPath);
validateInputDirectory(InRootPath);

// AnalysisScope defaults to the value of InRoot
// InRoot must be the same as or child of AnalysisScope
Expand All @@ -983,7 +948,7 @@ int runDPCT(int argc, const char **argv) {
}

if (isCUDAHeaderRequired())
ValidateInputDirectory(AnalysisScope);
validateInputDirectory(AnalysisScope);

if (GenHelperFunction.getValue()) {
dpct::genHelperFunction(dpct::DpctGlobalInfo::getOutRoot());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/DPCT/ErrorHandle/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ enum ProcessStatus {
MigrationErrorNoExplicitInRootAndBuildScript = -52,
MigrationErrorCannotWrite = -53,
MigratePythonBuildScriptOnlyNotSpecifed = -54,
};
};

namespace clang {
namespace dpct {
Expand Down