Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implementation of external intrinsics with processing & replacment header content #235

Open
wants to merge 10 commits into
base: devel
Choose a base branch
from
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -1131,4 +1131,4 @@ secring.*
*build*

.vscode/
lib/core/builtin_headers/okl_intrinsic_*
lib/core/intrinsics/okl_intrinsic_*
1 change: 1 addition & 0 deletions include/oklt/core/transpiler_session/user_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct UserInput {
std::vector<std::filesystem::path> includeDirectories; ///< The include directories.
std::vector<std::string> defines; ///< The defined macroses.
std::string hash; ///< OKL hash
std::vector<std::filesystem::path> userIntrinsics; ///< OKL user external intrincis folder
};

} // namespace oklt
14 changes: 8 additions & 6 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,10 @@ set (OCCA_TRANSPILER_SOURCES
core/rewriter/rewriter_proxy.cpp
core/rewriter/rewriter_fabric.cpp

core/builtin_headers/intrinsic_impl.cpp
core/builtin_headers/intrinsic_impl.h
core/intrinsics/builtin_intrinsics.h
core/intrinsics/builtin_intrinsics.cpp
core/intrinsics/external_intrinsics.h
core/intrinsics/external_intrinsics.cpp

core/handler_manager/handler_manager.cpp
core/handler_manager/handler_map.cpp
Expand Down Expand Up @@ -277,22 +279,22 @@ target_link_libraries(occa-transpiler
)

embed_resource_txt(${ROOT_DIR}/lib/resources/okl_intrinsic_cuda.h
${ROOT_DIR}/lib/core/builtin_headers/okl_intrinsic_cuda.h
${ROOT_DIR}/lib/core/intrinsics/okl_intrinsic_cuda.h
INTRINSIC_CUDA
)

embed_resource_txt(${ROOT_DIR}/lib/resources/okl_intrinsic_dpcpp.h
${ROOT_DIR}/lib/core/builtin_headers/okl_intrinsic_dpcpp.h
${ROOT_DIR}/lib/core/intrinsics/okl_intrinsic_dpcpp.h
INTRINSIC_DPCPP
)

embed_resource_txt(${ROOT_DIR}/lib/resources/okl_intrinsic_hip.h
${ROOT_DIR}/lib/core/builtin_headers/okl_intrinsic_hip.h
${ROOT_DIR}/lib/core/intrinsics/okl_intrinsic_hip.h
INTRINSIC_HIP
)

embed_resource_txt(${ROOT_DIR}/lib/resources/okl_intrinsic_host.h
${ROOT_DIR}/lib/core/builtin_headers/okl_intrinsic_host.h
${ROOT_DIR}/lib/core/intrinsics/okl_intrinsic_host.h
INTRINSIC_HOST
)

Expand Down
8 changes: 4 additions & 4 deletions lib/attributes/backend/launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ void collectLoops(OklLoopInfo& loopInfo, std::list<OklLoopInfo*>& out) {
}
#endif

std::pair<LoopMetaData, LoopMetaData> splitTileAttr(OklLoopInfo& loopInfo, const oklt::Rewriter& r) {
std::pair<LoopMetaData, LoopMetaData> splitTileAttr(OklLoopInfo& loopInfo,
const oklt::Rewriter& r) {
auto sz = util::parseStrTo<size_t>(loopInfo.tileSize);

// Prepare first loop
Expand Down Expand Up @@ -358,7 +359,6 @@ HandleResult handleLauncherTranslationUnit(SessionStage& s, const TranslationUni

SPDLOG_DEBUG("Handle translation unit");

// s.getRewriter().InsertTextBefore(loc, "#include " + includeOCCA + "\n\n");
auto& backendDeps = s.tryEmplaceUserCtx<HeaderDepsInfo>().backendHeaders;
backendDeps.clear();
backendDeps.emplace_back("#include " + std::string(includeOCCA) + "\n\n");
Expand All @@ -374,8 +374,8 @@ HandleResult handleLauncherKernelAttribute(SessionStage& s,
auto& rewriter = s.getRewriter();

if (!sema.getParsingKernelInfo()) {
return tl::make_unexpected(Error{OkltPipelineErrorCode::INTERNAL_ERROR_KERNEL_INFO_NULL,
"handleKernelAttribute"});
return tl::make_unexpected(
Error{OkltPipelineErrorCode::INTERNAL_ERROR_KERNEL_INFO_NULL, "handleKernelAttribute"});
}

auto kernelInfo = *sema.getParsingKernelInfo();
Expand Down
1 change: 0 additions & 1 deletion lib/attributes/utils/replace_attribute.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "attributes/utils/replace_attribute.h"
#include "attributes/attribute_names.h"
#include "core/builtin_headers/intrinsic_impl.h"
#include "core/transpiler_session/header_info.h"
#include "core/transpiler_session/session_stage.h"
#include "core/utils/var_decl.h"
Expand Down
7 changes: 4 additions & 3 deletions lib/core/diag/diag_consumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ DiagConsumer::DiagConsumer(SessionStage& session)
clang::DiagnosticConsumer(){};

void DiagConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic& Info) {
if (!_includeDiag.test_and_set()) {
if (!_includeDiag) {
_includeDiag = 1;
return;
}

Expand All @@ -44,13 +45,13 @@ bool DiagConsumer::IncludeInDiagnosticCounts() const {

// Accept only Warning, Error and Fatal
if (diagLevel < DiagnosticsEngine::Level::Warning) {
const_cast<std::atomic_flag&>(_includeDiag).clear();
_includeDiag = 0;
return false;
}

for (auto& ptr : getDiagDiagHandleInstances()) {
if (ptr->_id == info.getID() && ptr->HandleDiagnostic(_session, diagLevel, info)) {
const_cast<std::atomic_flag&>(_includeDiag).clear();
_includeDiag = 0;
return false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/core/diag/diag_consumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class DiagConsumer : public clang::DiagnosticConsumer {

protected:
SessionStage& _session;
std::atomic_flag _includeDiag = true;
mutable int _includeDiag = 0;
};

} // namespace oklt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "core/builtin_headers/intrinsic_impl.h"
#include "core/builtin_headers/okl_intrinsic_cuda.h"
#include "core/builtin_headers/okl_intrinsic_dpcpp.h"
#include "core/builtin_headers/okl_intrinsic_hip.h"
#include "core/builtin_headers/okl_intrinsic_host.h"
#include "core/intrinsics/builtin_intrinsics.h"
#include "core/intrinsics/okl_intrinsic_cuda.h"
#include "core/intrinsics/okl_intrinsic_dpcpp.h"
#include "core/intrinsics/okl_intrinsic_hip.h"
#include "core/intrinsics/okl_intrinsic_host.h"

#include <clang/Frontend/CompilerInstance.h>
#include "core/transpiler_session/transpiler_session.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ constexpr const char INTRINSIC_INCLUDE_FILENAME[] = "okl_intrinsic.h";
void addInstrinsicStub(TranspilerSession &session,
clang::CompilerInstance &compiler);


std::vector<std::string> embedInstrinsic(std::string &input,
TargetBackend backend);

Expand Down
158 changes: 158 additions & 0 deletions lib/core/intrinsics/external_intrinsics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#include "core/intrinsics/external_intrinsics.h"

#include <clang/Frontend/CompilerInstance.h>
#include "core/transpiler_session/transpiler_session.h"
#include "util/string_utils.hpp"

#include <algorithm>
#include <optional>

namespace oklt {

using namespace llvm;
namespace fs = std::filesystem;

tl::expected<fs::path, std::string> getIntrincisImplSourcePath(TargetBackend backend,
const fs::path& intrincisPath) {
switch (backend) {
case TargetBackend::CUDA:
return intrincisPath / "cuda";
case TargetBackend::HIP:
return intrincisPath / "hip";
case TargetBackend::DPCPP:
return intrincisPath / "dpcpp";
case TargetBackend::OPENMP:
return intrincisPath / "openmp";
case TargetBackend::SERIAL:
return intrincisPath / "serial";
default:
return tl::make_unexpected("User intrinsic does not implement target backend");
}
}

bool isExternalIntrinsicInclude(TranspilerSession& session, const std::string& fileName) {
const auto& userIntrinsic = session.getInput().userIntrinsics;
if (userIntrinsic.empty()) {
return false;
}
auto normalizedName = fileName;
if (util::startsWith(normalizedName, "./")) {
normalizedName = normalizedName.substr(2);
}
for (const auto& intrinsic : userIntrinsic) {
auto folderPrefix = intrinsic.filename().string();
if (util::startsWith(normalizedName, folderPrefix)) {
return true;
}
}
return false;
}

std::optional<fs::path> getExternalInstrincisInclude(TranspilerSession& session,
const std::string& fileName) {
const auto& userIntrinsic = session.getInput().userIntrinsics;
if (userIntrinsic.empty()) {
return std::nullopt;
}
for (const auto& intrinsic : userIntrinsic) {
auto folderPrefix = intrinsic.filename().string();
if (util::startsWith(fileName, folderPrefix)) {
return intrinsic;
}
}
return std::nullopt;
}

tl::expected<std::unique_ptr<llvm::MemoryBuffer>, std::string> getExternalIntrinsicSource(
TargetBackend backend,
const fs::path& intrinsicPath,
clang::SourceManager& sm) {
auto implPathResult = getIntrincisImplSourcePath(backend, intrinsicPath);
if (!implPathResult) {
return tl::make_unexpected(implPathResult.error());
}

auto sourceFolder = implPathResult.value();
if (!std::filesystem::exists(sourceFolder)) {
return tl::make_unexpected("Intrinsic implementation folder does not exist");
}

std::vector<fs::path> files(fs::directory_iterator(sourceFolder), {});
if (files.empty()) {
return tl::make_unexpected("Intrinsic implementation files is missing");
}

auto it = std::find_if(files.cbegin(), files.cend(), [](const fs::path& p) -> bool {
return p.extension().string() == std::string(".h");
});

if (it == files.cend()) {
std::string error = "Can't' find implementation file with path: " + sourceFolder.string();
return tl::make_unexpected(error);
}

auto& fm = sm.getFileManager();
auto backendFilePath = it->string();
auto maybeReplacedFile = fm.getFile(backendFilePath);
if (!maybeReplacedFile) {
std::string error = "Can't open file: " + backendFilePath;
return tl::make_unexpected(error);
}
auto maybeBuffer = fm.getBufferForFile(maybeReplacedFile.get());
if (!maybeBuffer) {
std::string error = "Can't get memory buffer for: " + backendFilePath;
return tl::make_unexpected(error);
}
return std::move(maybeBuffer.get());
}

bool overrideExternalIntrinsic(TranspilerSession& session,
const std::string& includedFileName,
clang::OptionalFileEntryRef includedFile,
clang::SourceManager& sourceManager) {
const auto& userIntrinsics = session.getInput().userIntrinsics;
if (!userIntrinsics.empty()) {
auto maybeIntrinsicPath = getExternalInstrincisInclude(session, includedFileName);
if (!maybeIntrinsicPath) {
return false;
}
auto intrinsicPath = maybeIntrinsicPath.value();
auto infoResult =
getExternalIntrinsicSource(session.getInput().backend, intrinsicPath, sourceManager);
if (!infoResult) {
session.pushError(std::error_code(), infoResult.error());
return false;
}
auto buffer = std::move(infoResult.value());
auto& fm = sourceManager.getFileManager();
if (includedFile) {
auto fileRef = includedFile;
const auto& fileEntry = fileRef->getFileEntry();
sourceManager.overrideFileContents(&fileEntry, std::move(buffer));
} else {
// INFO: case when the file can be found by relative path
// it happens when the include path is relative to WORKING DIR path
auto maybeFileRef = fm.getFileRef(includedFileName);
if (maybeFileRef) {
auto foundFileRef = maybeFileRef.get();
sourceManager.overrideFileContents(foundFileRef, std::move(buffer));
}
}
return true;
}
return false;
}

void nullyExternalIntrinsics(TransformedFiles& inputs, TranspilerSession& session) {
const auto& intrinsics = session.getInput().userIntrinsics;
if (intrinsics.empty()) {
return;
}
for (auto& mappedFile : inputs.fileMap) {
if (isExternalIntrinsicInclude(session, mappedFile.first)) {
mappedFile.second.clear();
}
}
}

} // namespace oklt
22 changes: 22 additions & 0 deletions lib/core/intrinsics/external_intrinsics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once
#include <clang/Basic/FileEntry.h>
#include <string>

namespace clang {
class CompilerInstance;
class SourceManager;
} // namespace clang

namespace oklt {

class TranspilerSession;
class TransformedFiles;

bool overrideExternalIntrinsic(TranspilerSession& session,
const std::string& includedFileName,
clang::OptionalFileEntryRef includedFile,
clang::SourceManager& sourceManager);

void nullyExternalIntrinsics(TransformedFiles& inputs, TranspilerSession& session);

} // namespace oklt
Loading