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
177 changes: 177 additions & 0 deletions lib/core/intrinsics/external_intrinsics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#include "core/intrinsics/external_intrinsics.h"

#include <clang/Frontend/CompilerInstance.h>
#include "core/transpiler_session/session_stage.h"
#include "core/transpiler_session/transpiler_session.h"
#include "oklt/util/io_helper.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";
case TargetBackend::_LAUNCHER:
return intrincisPath / "launcher";
default:
return tl::make_unexpected("User intrinsic does not implement target backend");
}
}

std::string normalizedFileName(const std::string& fileName) {
auto normalizedName = fileName;
if (util::startsWith(normalizedName, "./")) {
normalizedName = normalizedName.substr(2);
}
return normalizedName;
}

bool isExternalIntrinsicInclude(TranspilerSession& session, const std::string& fileName) {
const auto& userIntrinsic = session.getInput().userIntrinsics;
if (userIntrinsic.empty()) {
return false;
}
auto normalizedName = normalizedFileName(fileName);
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;
}

auto normalizedName = normalizedFileName(fileName);
for (const auto& intrinsic : userIntrinsic) {
auto folderPrefix = intrinsic.filename().string();
if (util::startsWith(normalizedName, folderPrefix)) {
return intrinsic;
}
}
return std::nullopt;
}

tl::expected<std::string, 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(".cpp");
});

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

auto contentResult = util::readFileAsStr(*it);
if (!contentResult) {
std::string error = "Can't get memory buffer for: " + it->string();
return tl::make_unexpected(error);
}
return contentResult.value();
}

bool overrideExternalIntrinsic(SessionStage& stage,
HeaderDepsInfo& deps,
const std::string& includedFileName,
clang::OptionalFileEntryRef includedFile) {
auto& session = stage.getSession();
auto& sourceManager = stage.getCompiler().getSourceManager();
const auto& userIntrinsics = session.getInput().userIntrinsics;
if (!userIntrinsics.empty()) {
auto maybeIntrinsicPath = getExternalInstrincisInclude(session, includedFileName);
if (!maybeIntrinsicPath) {
return false;
}
auto intrinsicPath = maybeIntrinsicPath.value();
auto intrinsicResult =
getExternalIntrinsicSource(stage.getBackend(), intrinsicPath, sourceManager);
if (!intrinsicResult) {
session.pushError(std::error_code(), intrinsicResult.error());
return false;
}
deps.externalIntrinsicsSources[includedFileName] = std::move(intrinsicResult.value());

auto emptyExternalIntrinsic = MemoryBuffer::getMemBuffer("");
if (includedFile) {
auto fileRef = includedFile;
const auto& fileEntry = fileRef->getFileEntry();
sourceManager.overrideFileContents(&fileEntry, std::move(emptyExternalIntrinsic));
} 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& fm = sourceManager.getFileManager();
auto maybeFileRef = fm.getFileRef(includedFileName);
if (maybeFileRef) {
auto foundFileRef = maybeFileRef.get();
sourceManager.overrideFileContents(foundFileRef, std::move(emptyExternalIntrinsic));
}
}
return true;
}
return false;
}

void updateExternalIntrinsicMap(SessionStage& stage, HeaderDepsInfo& deps) {
if (deps.externalIntrinsicsSources.empty()) {
return;
}

auto backend = stage.getBackend();
auto& session = stage.getSession();
auto& sm = stage.getCompiler().getSourceManager();
for (auto& mappedIntrinsic : deps.externalIntrinsicsSources) {
auto maybeIntrinsicPath = getExternalInstrincisInclude(session, mappedIntrinsic.first);
if (!maybeIntrinsicPath) {
std::string error = "Count not find implementation for " + mappedIntrinsic.first;
session.pushError(std::error_code(), error);
return;
}
auto intrinsicPath = maybeIntrinsicPath.value();
auto intrinsicResult = getExternalIntrinsicSource(backend, intrinsicPath, sm);
if (!intrinsicResult) {
session.pushError(std::error_code(), intrinsicResult.error());
return;
}
mappedIntrinsic.second = std::move(intrinsicResult.value());
}
}
} // namespace oklt
16 changes: 16 additions & 0 deletions lib/core/intrinsics/external_intrinsics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once
#include <clang/Basic/FileEntry.h>
#include <string>

namespace oklt {

class SessionStage;
class HeaderDepsInfo;

bool overrideExternalIntrinsic(SessionStage& stage,
HeaderDepsInfo& deps,
const std::string& includedFileName,
clang::OptionalFileEntryRef includedFile);

void updateExternalIntrinsicMap(SessionStage& stage, HeaderDepsInfo& deps);
} // namespace oklt
Loading