refactor: ocloc command line refactor

Related-To: NEO-14135

Signed-off-by: Chodor, Jaroslaw <jaroslaw.chodor@intel.com>
This commit is contained in:
Chodor, Jaroslaw
2025-01-24 12:14:19 +00:00
committed by Compute-Runtime-Automation
parent 291745cdf7
commit 8040d8bebf
10 changed files with 240 additions and 84 deletions

View File

@@ -100,6 +100,8 @@ set(CLOC_LIB_SRCS_LIB
${OCLOC_DIRECTORY}/source/multi_command.h
${OCLOC_DIRECTORY}/source/ocloc_api.cpp
${OCLOC_DIRECTORY}/source/ocloc_api.h
${OCLOC_DIRECTORY}/source/offline_compiler_ext.h
${OCLOC_DIRECTORY}/source${BRANCH_DIR_SUFFIX}/offline_compiler_ext.cpp
${OCLOC_DIRECTORY}/source/ocloc_arg_helper.cpp
${OCLOC_DIRECTORY}/source/ocloc_arg_helper.h
${OCLOC_DIRECTORY}/source/ocloc_concat.cpp

View File

@@ -32,6 +32,7 @@
#include "shared/source/helpers/validators.h"
#include "shared/source/release_helper/release_helper.h"
#include "offline_compiler_ext.h"
#include "platforms.h"
#include <iomanip>
@@ -489,13 +490,8 @@ struct OfflineCompiler::BuildInfo {
IGC::CodeType::CodeType_t intermediateRepresentation;
};
int OfflineCompiler::buildIrBinary() {
int OfflineCompiler::buildToIrBinary() {
int retVal = OCLOC_SUCCESS;
pBuildInfo->intermediateRepresentation = preferredIntermediateRepresentation;
if (inputFileLlvm) {
pBuildInfo->intermediateRepresentation = useLlvmText ? IGC::CodeType::llvmLl : IGC::CodeType::llvmBc;
}
isSpirV = pBuildInfo->intermediateRepresentation == IGC::CodeType::spirV;
if (allowCaching) {
const std::string igcRevision = igcFacade->getIgcRevision();
@@ -541,7 +537,7 @@ int OfflineCompiler::buildIrBinary() {
fclSrc = fclFacade->createConstBuffer(sourceCode.c_str(), sourceCode.size() + 1);
}
auto fclTranslationCtx = fclFacade->createTranslationContext(srcType, pBuildInfo->intermediateRepresentation, err.get());
auto fclTranslationCtx = fclFacade->createTranslationContext(srcType, intermediateRepresentation, err.get());
if (true == NEO::areNotNullptr(err->GetMemory<char>())) {
updateBuildLog(err->GetMemory<char>(), err->GetSizeRaw());
@@ -572,6 +568,7 @@ int OfflineCompiler::buildIrBinary() {
return retVal;
}
pBuildInfo->intermediateRepresentation = intermediateRepresentation;
storeBinary(irBinary, irBinarySize, pBuildInfo->fclOutput->GetOutput()->GetMemory<char>(), pBuildInfo->fclOutput->GetOutput()->GetSizeRaw());
updateBuildLog(pBuildInfo->fclOutput->GetBuildLog()->GetMemory<char>(), pBuildInfo->fclOutput->GetBuildLog()->GetSizeRaw());
@@ -616,18 +613,14 @@ int OfflineCompiler::buildSourceCode() {
if (sourceCode.empty()) {
return OCLOC_INVALID_PROGRAM;
}
auto inputTypeWarnings = validateInputType(sourceCode, inputFileLlvm, inputFileSpirV);
auto inputTypeWarnings = validateInputType(sourceCode, inputFileLlvm(), inputFileSpirV());
this->argHelper->printf(inputTypeWarnings.c_str());
bool inputIsIntermediateRepresentation = inputFileLlvm || inputFileSpirV;
if (inputIsIntermediateRepresentation) {
if (isIntermediateRepresentation(this->inputCodeType)) {
storeBinary(irBinary, irBinarySize, sourceCode.c_str(), sourceCode.size());
auto asBitcode = ArrayRef<const uint8_t>::fromAny(irBinary, irBinarySize);
isSpirV = NEO::isSpirVBitcode(asBitcode);
pBuildInfo->intermediateRepresentation = isSpirV ? IGC::CodeType::spirV : IGC::CodeType::llvmBc;
pBuildInfo->intermediateRepresentation = this->inputCodeType;
} else {
retVal = buildIrBinary();
pBuildInfo->intermediateRepresentation = (this->intermediateRepresentation != IGC::CodeType::undefined) ? this->intermediateRepresentation : this->preferredIntermediateRepresentation;
retVal = buildToIrBinary();
if (retVal != OCLOC_SUCCESS)
return retVal;
}
@@ -709,16 +702,16 @@ int OfflineCompiler::build() {
if (sourceFromFileSize == 0) {
return OCLOC_INVALID_FILE;
}
if (inputFileLlvm || inputFileSpirV) {
// use the binary input "as is"
sourceCode.assign(sourceFromFile.get(), sourceFromFileSize);
} else {
if (this->inputCodeType == IGC::CodeType::oclC) {
// for text input, we also accept files used as runtime builtins
source = strstr((const char *)sourceFromFile.get(), "R\"===(");
sourceCode = (source != nullptr) ? getStringWithinDelimiters(sourceFromFile.get()) : sourceFromFile.get();
} else {
// use the binary input "as is"
sourceCode.assign(sourceFromFile.get(), sourceFromFileSize);
}
if ((inputFileSpirV == false) && (inputFileLlvm == false)) {
if (this->inputCodeType == IGC::CodeType::oclC) {
const auto fclInitializationResult = fclFacade->initialize(hwInfo);
if (fclInitializationResult != OCLOC_SUCCESS) {
argHelper->printf("Error! FCL initialization failure. Error code = %d\n", fclInitializationResult);
@@ -733,6 +726,10 @@ int OfflineCompiler::build() {
preferredIntermediateRepresentation = IGC::CodeType::spirV;
}
if (intermediateRepresentation == IGC::CodeType::undefined) {
intermediateRepresentation = preferredIntermediateRepresentation;
}
const auto igcInitializationResult = igcFacade->initialize(hwInfo);
if (igcInitializationResult != OCLOC_SUCCESS) {
argHelper->printf("Error! IGC initialization failure. Error code = %d\n", igcInitializationResult);
@@ -741,7 +738,7 @@ int OfflineCompiler::build() {
int retVal = OCLOC_SUCCESS;
if (isOnlySpirV()) {
retVal = buildIrBinary();
retVal = buildToIrBinary();
} else {
retVal = buildSourceCode();
}
@@ -952,7 +949,7 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector<std::string> &
enforceFormat(formatToEnforce);
}
if (CompilerOptions::contains(options, CompilerOptions::generateDebugInfo.str())) {
if (false == inputFileSpirV && false == CompilerOptions::contains(options, CompilerOptions::generateSourcePath) && false == CompilerOptions::contains(options, CompilerOptions::useCMCompiler)) {
if (false == inputFileSpirV() && false == CompilerOptions::contains(options, CompilerOptions::generateSourcePath) && false == CompilerOptions::contains(options, CompilerOptions::useCMCompiler)) {
auto sourcePathStringOption = CompilerOptions::generateSourcePath.str();
sourcePathStringOption.append(" ");
sourcePathStringOption.append(CompilerOptions::wrapInQuotes(inputFile));
@@ -1015,13 +1012,21 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vector<std::str
deviceName = argv[argIndex + 1];
argIndex++;
} else if ("-llvm_text" == currArg) {
useLlvmText = true;
if (this->inputCodeType == IGC::CodeType::llvmBc) {
this->inputCodeType = IGC::CodeType::llvmLl;
}
this->intermediateRepresentation = IGC::CodeType::llvmLl;
} else if ("-llvm_bc" == currArg) {
useLlvmBc = true;
if (this->inputCodeType == IGC::CodeType::llvmLl) {
this->inputCodeType = IGC::CodeType::llvmBc;
}
this->intermediateRepresentation = IGC::CodeType::llvmBc;
} else if ("-llvm_input" == currArg) {
inputFileLlvm = true;
this->inputCodeType = (this->intermediateRepresentation == IGC::CodeType::llvmLl) ? IGC::CodeType::llvmLl : IGC::CodeType::llvmBc;
this->intermediateRepresentation = this->inputCodeType;
} else if ("-spirv_input" == currArg) {
inputFileSpirV = true;
this->inputCodeType = IGC::CodeType::spirV;
this->intermediateRepresentation = IGC::CodeType::spirV;
} else if ("-cpp_file" == currArg) {
useCppFile = true;
} else if ("-gen_file" == currArg) {
@@ -1099,9 +1104,11 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vector<std::str
} else if ("-allow_caching" == currArg) {
allowCaching = true;
} else {
argHelper->printf("Invalid option (arg %d): %s\n", argIndex, argv[argIndex].c_str());
retVal = OCLOC_INVALID_COMMAND_LINE;
break;
retVal = parseCommandLineExt(numArgs, argv, argIndex);
if (OCLOC_INVALID_COMMAND_LINE == retVal) {
argHelper->printf("Invalid option (arg %u): %s\n", argIndex, argv[argIndex].c_str());
break;
}
}
}
@@ -1432,13 +1439,14 @@ Usage: ocloc [compile] -file <filename> -device <device_type> [-output <filename
-config Target hardware info config for a single device,
e.g 1x4x8.
%s
Examples :
Compile file to Intel Compute GPU device binary (out = source_file_Gen9core.bin)
ocloc -file source_file.cl -device skl
)OCLOC_HELP",
getSupportedDevices(argHelper).c_str(),
getDeprecatedDevices(argHelper).c_str());
getDeprecatedDevices(argHelper).c_str(),
getOfflineCompilerOptionsExt().c_str());
}
void OfflineCompiler::storeBinary(
@@ -1500,7 +1508,7 @@ bool OfflineCompiler::generateElfBinary() {
}
if (!binary.intermediateRepresentation.empty() && !excludeIr) {
if (isSpirV) {
if (this->intermediateRepresentation == IGC::CodeType::spirV) {
elfEncoder.appendSection(SHT_OPENCL_SPIRV, SectionNamesOpenCl::spirvObject, binary.intermediateRepresentation);
} else {
elfEncoder.appendSection(SHT_OPENCL_LLVM_BINARY, SectionNamesOpenCl::llvmObject, binary.intermediateRepresentation);
@@ -1566,7 +1574,7 @@ void OfflineCompiler::writeOutAllFiles() {
return;
}
if (irBinary && !inputFileSpirV) {
if (irBinary && (this->inputCodeType != IGC::CodeType::spirV)) {
std::string irOutputFileName = generateFilePathForIr(fileBase) + generateOptsSuffix();
argHelper->saveOutput(irOutputFileName, irBinary, irBinarySize);

View File

@@ -46,6 +46,23 @@ static_assert(sizeof(NameVersionPair) == sizeof(ocloc_name_version));
const HardwareInfo *getHwInfoForDeprecatedAcronym(const std::string &deviceName);
constexpr bool isIntermediateRepresentation(IGC::CodeType::CodeType_t codeType) {
return false == ((IGC::CodeType::oclC == codeType) || (IGC::CodeType::oclCpp == codeType) || (IGC::CodeType::oclGenBin == codeType));
}
constexpr const char *getFileExtension(IGC::CodeType::CodeType_t codeType) {
switch (codeType) {
default:
return ".bin";
case IGC::CodeType::llvmBc:
return ".bc";
case IGC::CodeType::llvmLl:
return ".ll";
case IGC::CodeType::spirV:
return ".spv";
}
}
class OfflineCompiler : NEO::NonCopyableAndNonMovableClass {
public:
static std::vector<NameVersionPair> getExtensions(ConstStringRef product, bool needVersions, OclocArgHelper *helper);
@@ -158,18 +175,19 @@ All supported acronyms: %s.
std::string getStringWithinDelimiters(const std::string &src);
int initialize(size_t numArgs, const std::vector<std::string> &allArgs, bool dumpFiles);
int parseCommandLine(size_t numArgs, const std::vector<std::string> &allArgs);
int parseCommandLineExt(size_t numArgs, const std::vector<std::string> &allArgs, uint32_t &argIndex);
void setStatelessToStatefulBufferOffsetFlag();
void appendExtraInternalOptions(std::string &internalOptions);
void parseDebugSettings();
void storeBinary(char *&pDst, size_t &dstSize, const void *pSrc, const size_t srcSize);
MOCKABLE_VIRTUAL int buildSourceCode();
MOCKABLE_VIRTUAL std::string validateInputType(const std::string &input, bool isLlvm, bool isSpirv);
MOCKABLE_VIRTUAL int buildIrBinary();
MOCKABLE_VIRTUAL int buildToIrBinary();
void updateBuildLog(const char *pErrorString, const size_t errorStringSize);
MOCKABLE_VIRTUAL bool generateElfBinary();
std::string generateFilePathForIr(const std::string &fileNameBase) {
const char *ext = (isSpirV) ? ".spv" : ".bc";
return generateFilePath(outputDirectory, fileNameBase, useLlvmText ? ".ll" : ext);
const char *ext = getFileExtension(intermediateRepresentation);
return generateFilePath(outputDirectory, fileNameBase, ext);
}
std::string generateOptsSuffix() {
@@ -206,18 +224,25 @@ All supported acronyms: %s.
bool allowCaching = false;
bool dumpFiles = true;
bool useLlvmText = false;
bool useLlvmBc = false;
bool useCppFile = false;
bool useGenFile = false;
bool useOptionsSuffix = false;
bool quiet = false;
bool onlySpirV = false;
bool inputFileLlvm = false;
bool inputFileSpirV = false;
bool useLlvmTxt = false;
IGC::CodeType::CodeType_t inputCodeType = IGC::CodeType::oclC;
bool inputFileLlvm() const {
return (IGC::CodeType::llvmBc == inputCodeType) || (IGC::CodeType::llvmLl == inputCodeType);
}
bool inputFileSpirV() const {
return IGC::CodeType::spirV == inputCodeType;
}
bool outputNoSuffix = false;
bool forceStatelessToStatefulOptimization = false;
bool isSpirV = true;
bool showHelp = false;
bool excludeIr = false;
@@ -240,6 +265,7 @@ All supported acronyms: %s.
std::unique_ptr<CompilerProductHelper> compilerProductHelper;
std::unique_ptr<ReleaseHelper> releaseHelper;
IGC::CodeType::CodeType_t preferredIntermediateRepresentation;
IGC::CodeType::CodeType_t intermediateRepresentation = IGC::CodeType::undefined;
OclocArgHelper *argHelper = nullptr;
};

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/offline_compiler/source/offline_compiler_ext.h"
#include "shared/offline_compiler/source/offline_compiler.h"
namespace NEO {
std::string getOfflineCompilerOptionsExt() {
return "";
}
int OfflineCompiler::parseCommandLineExt(size_t numArgs, const std::vector<std::string> &argv, uint32_t &argIndex) {
return OCLOC_INVALID_COMMAND_LINE;
}
} // namespace NEO

View File

@@ -0,0 +1,16 @@
/*
* Copyright (C) 2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <string>
namespace NEO {
std::string getOfflineCompilerOptionsExt();
}